xref: /AOO41X/main/forms/source/component/FormattedField.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 
27 #include "FormattedField.hxx"
28 #include "services.hxx"
29 #include "property.hrc"
30 #include "property.hxx"
31 #include "frm_resource.hxx"
32 #include "frm_resource.hrc"
33 #include "propertybaghelper.hxx"
34 #include <comphelper/sequence.hxx>
35 #include <comphelper/numbers.hxx>
36 #include <connectivity/dbtools.hxx>
37 #include <connectivity/dbconversion.hxx>
38 #include <svl/zforlist.hxx>
39 #include <svl/numuno.hxx>
40 #include <vcl/svapp.hxx>
41 #include <tools/debug.hxx>
42 #include <tools/wintypes.hxx>
43 #include <i18npool/mslangid.hxx>
44 #include <rtl/textenc.h>
45 #include <com/sun/star/sdbc/DataType.hpp>
46 #include <com/sun/star/util/NumberFormat.hpp>
47 #include <com/sun/star/util/Date.hpp>
48 #include <com/sun/star/util/Time.hpp>
49 #include <com/sun/star/awt/MouseEvent.hpp>
50 #include <com/sun/star/form/XSubmit.hpp>
51 #include <com/sun/star/awt/XWindow.hpp>
52 #include <com/sun/star/awt/XKeyListener.hpp>
53 #include <com/sun/star/form/FormComponentType.hpp>
54 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
55 #include <com/sun/star/util/XNumberFormatTypes.hpp>
56 #include <com/sun/star/form/XForm.hpp>
57 #include <com/sun/star/container/XIndexAccess.hpp>
58 #include <vos/mutex.hxx>
59     // needed as long as we use the SolarMutex
60 #include <comphelper/streamsection.hxx>
61 #include <cppuhelper/weakref.hxx>
62 #include <unotools/desktopterminationobserver.hxx>
63 
64 #include <list>
65 #include <algorithm>
66 
67 using namespace dbtools;
68 using namespace ::com::sun::star::uno;
69 using namespace ::com::sun::star::sdb;
70 using namespace ::com::sun::star::sdbc;
71 using namespace ::com::sun::star::sdbcx;
72 using namespace ::com::sun::star::beans;
73 using namespace ::com::sun::star::container;
74 using namespace ::com::sun::star::form;
75 using namespace ::com::sun::star::awt;
76 using namespace ::com::sun::star::io;
77 using namespace ::com::sun::star::lang;
78 using namespace ::com::sun::star::util;
79 using namespace ::com::sun::star::form::binding;
80 
81 namespace
82 {
83     typedef com::sun::star::util::Date UNODate;
84     typedef com::sun::star::util::Time UNOTime;
85     typedef com::sun::star::util::DateTime UNODateTime;
86 }
87 
88 //.........................................................................
89 namespace frm
90 {
91 
92 /*************************************************************************/
93 
94 class StandardFormatsSupplier : protected SvNumberFormatsSupplierObj, public ::utl::ITerminationListener
95 {
96 protected:
97             SvNumberFormatter*                       m_pMyPrivateFormatter;
98     static  WeakReference< XNumberFormatsSupplier >  s_xDefaultFormatsSupplier;
99 
100 public:
101     static Reference< XNumberFormatsSupplier > get( const Reference< XMultiServiceFactory >& _rxORB );
102 
103     using SvNumberFormatsSupplierObj::operator new;
104     using SvNumberFormatsSupplierObj::operator delete;
105 
106 protected:
107     StandardFormatsSupplier(const Reference<XMultiServiceFactory>& _rxFactory,LanguageType _eSysLanguage);
108     ~StandardFormatsSupplier();
109 
110 protected:
111     virtual bool    queryTermination() const;
112     virtual void    notifyTermination();
113 };
114 
115 //------------------------------------------------------------------
116 WeakReference< XNumberFormatsSupplier > StandardFormatsSupplier::s_xDefaultFormatsSupplier;
117 
118 //------------------------------------------------------------------
StandardFormatsSupplier(const Reference<XMultiServiceFactory> & _rxFactory,LanguageType _eSysLanguage)119 StandardFormatsSupplier::StandardFormatsSupplier(const Reference< XMultiServiceFactory > & _rxFactory,LanguageType _eSysLanguage)
120     :SvNumberFormatsSupplierObj()
121     ,m_pMyPrivateFormatter(new SvNumberFormatter(_rxFactory, _eSysLanguage))
122 {
123     SetNumberFormatter(m_pMyPrivateFormatter);
124 
125     // #i29147# - 2004-06-18 - fs@openoffice.org
126     ::utl::DesktopTerminationObserver::registerTerminationListener( this );
127 }
128 
129 //------------------------------------------------------------------
~StandardFormatsSupplier()130 StandardFormatsSupplier::~StandardFormatsSupplier()
131 {
132     ::utl::DesktopTerminationObserver::revokeTerminationListener( this );
133 
134     DELETEZ( m_pMyPrivateFormatter );
135 }
136 
137 //------------------------------------------------------------------
get(const Reference<XMultiServiceFactory> & _rxORB)138 Reference< XNumberFormatsSupplier > StandardFormatsSupplier::get( const Reference< XMultiServiceFactory >& _rxORB )
139 {
140     LanguageType eSysLanguage = LANGUAGE_SYSTEM;
141     {
142         ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
143         Reference< XNumberFormatsSupplier > xSupplier = s_xDefaultFormatsSupplier;
144         if ( xSupplier.is() )
145             return xSupplier;
146 
147         // get the Office's locale
148         const Locale& rSysLocale = SvtSysLocale().GetLocaleData().getLocale();
149         // translate
150         eSysLanguage = MsLangId::convertLocaleToLanguage( rSysLocale );
151     }
152 
153     StandardFormatsSupplier* pSupplier = new StandardFormatsSupplier( _rxORB, eSysLanguage );
154     Reference< XNumberFormatsSupplier > xNewlyCreatedSupplier( pSupplier );
155 
156     {
157         ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
158         Reference< XNumberFormatsSupplier > xSupplier = s_xDefaultFormatsSupplier;
159         if ( xSupplier.is() )
160             // somebody used the small time frame where the mutex was not locked to create and set
161             // the supplier
162             return xSupplier;
163 
164         s_xDefaultFormatsSupplier = xNewlyCreatedSupplier;
165     }
166 
167     return xNewlyCreatedSupplier;
168 }
169 
170 //------------------------------------------------------------------
queryTermination() const171 bool StandardFormatsSupplier::queryTermination() const
172 {
173     return true;
174 }
175 
176 //------------------------------------------------------------------
notifyTermination()177 void StandardFormatsSupplier::notifyTermination()
178 {
179     Reference< XNumberFormatsSupplier > xKeepAlive = this;
180     // when the application is terminating, release our static reference so that we are cleared/destructed
181     // earlier than upon unloading the library
182     // #i29147# - 2004-06-18 - fs@openoffice.org
183     s_xDefaultFormatsSupplier = WeakReference< XNumberFormatsSupplier >( );
184 
185     SetNumberFormatter( NULL );
186     DELETEZ( m_pMyPrivateFormatter );
187 }
188 
189 /*************************************************************************/
190 //------------------------------------------------------------------
OFormattedControl_CreateInstance(const Reference<XMultiServiceFactory> & _rxFactory)191 InterfaceRef SAL_CALL OFormattedControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory)
192 {
193     return *(new OFormattedControl(_rxFactory));
194 }
195 
196 //------------------------------------------------------------------
_getTypes()197 Sequence<Type> OFormattedControl::_getTypes()
198 {
199     return ::comphelper::concatSequences(
200         OFormattedControl_BASE::getTypes(),
201         OBoundControl::_getTypes()
202     );
203 }
204 
205 //------------------------------------------------------------------
queryAggregation(const Type & _rType)206 Any SAL_CALL OFormattedControl::queryAggregation(const Type& _rType) throw (RuntimeException)
207 {
208     Any aReturn = OBoundControl::queryAggregation(_rType);
209     if (!aReturn.hasValue())
210         aReturn = OFormattedControl_BASE::queryInterface(_rType);
211     return aReturn;
212 }
213 
214 
215 DBG_NAME(OFormattedControl);
216 //------------------------------------------------------------------------------
OFormattedControl(const Reference<XMultiServiceFactory> & _rxFactory)217 OFormattedControl::OFormattedControl(const Reference<XMultiServiceFactory>& _rxFactory)
218                :OBoundControl(_rxFactory, VCL_CONTROL_FORMATTEDFIELD)
219                ,m_nKeyEvent(0)
220 {
221     DBG_CTOR(OFormattedControl,NULL);
222 
223     increment(m_refCount);
224     {
225         Reference<XWindow>  xComp;
226         if (query_aggregation(m_xAggregate, xComp))
227         {
228             xComp->addKeyListener(this);
229         }
230     }
231     decrement(m_refCount);
232 }
233 
234 //------------------------------------------------------------------------------
~OFormattedControl()235 OFormattedControl::~OFormattedControl()
236 {
237     if( m_nKeyEvent )
238         Application::RemoveUserEvent( m_nKeyEvent );
239 
240     if (!OComponentHelper::rBHelper.bDisposed)
241     {
242         acquire();
243         dispose();
244     }
245 
246     DBG_DTOR(OFormattedControl,NULL);
247 }
248 
249 // XKeyListener
250 //------------------------------------------------------------------------------
disposing(const EventObject & _rSource)251 void OFormattedControl::disposing(const EventObject& _rSource) throw(RuntimeException)
252 {
253     OBoundControl::disposing(_rSource);
254 }
255 
256 //------------------------------------------------------------------------------
keyPressed(const::com::sun::star::awt::KeyEvent & e)257 void OFormattedControl::keyPressed(const ::com::sun::star::awt::KeyEvent& e) throw ( ::com::sun::star::uno::RuntimeException)
258 {
259     if( e.KeyCode != KEY_RETURN || e.Modifiers != 0 )
260         return;
261 
262     // Steht das Control in einem Formular mit einer Submit-URL?
263     Reference<com::sun::star::beans::XPropertySet>  xSet(getModel(), UNO_QUERY);
264     if( !xSet.is() )
265         return;
266 
267     Reference<XFormComponent>  xFComp(xSet, UNO_QUERY);
268     InterfaceRef  xParent = xFComp->getParent();
269     if( !xParent.is() )
270         return;
271 
272     Reference<com::sun::star::beans::XPropertySet>  xFormSet(xParent, UNO_QUERY);
273     if( !xFormSet.is() )
274         return;
275 
276     Any aTmp(xFormSet->getPropertyValue( PROPERTY_TARGET_URL ));
277     if (!isA(aTmp, static_cast< ::rtl::OUString* >(NULL)) ||
278         !getString(aTmp).getLength() )
279         return;
280 
281     Reference<XIndexAccess>  xElements(xParent, UNO_QUERY);
282     sal_Int32 nCount = xElements->getCount();
283     if( nCount > 1 )
284     {
285 
286         Reference<com::sun::star::beans::XPropertySet>  xFCSet;
287         for( sal_Int32 nIndex=0; nIndex < nCount; nIndex++ )
288         {
289             //  Any aElement(xElements->getByIndex(nIndex));
290             xElements->getByIndex(nIndex) >>= xFCSet;
291 
292             if (hasProperty(PROPERTY_CLASSID, xFCSet) &&
293                 getINT16(xFCSet->getPropertyValue(PROPERTY_CLASSID)) == FormComponentType::TEXTFIELD)
294             {
295                 // Noch ein weiteres Edit gefunden ==> dann nicht submitten
296                 if (xFCSet != xSet)
297                     return;
298             }
299         }
300     }
301 
302     // Da wir noch im Haender stehen, submit asynchron ausloesen
303     if( m_nKeyEvent )
304         Application::RemoveUserEvent( m_nKeyEvent );
305     m_nKeyEvent = Application::PostUserEvent( LINK(this, OFormattedControl,
306                                             OnKeyPressed) );
307 }
308 
309 //------------------------------------------------------------------------------
keyReleased(const::com::sun::star::awt::KeyEvent &)310 void OFormattedControl::keyReleased(const ::com::sun::star::awt::KeyEvent& /*e*/) throw ( ::com::sun::star::uno::RuntimeException)
311 {
312 }
313 
314 //------------------------------------------------------------------------------
315 IMPL_LINK(OFormattedControl, OnKeyPressed, void*, /*EMPTYARG*/)
316 {
317     m_nKeyEvent = 0;
318 
319     Reference<XFormComponent>  xFComp(getModel(), UNO_QUERY);
320     InterfaceRef  xParent = xFComp->getParent();
321     Reference<XSubmit>  xSubmit(xParent, UNO_QUERY);
322     if (xSubmit.is())
323         xSubmit->submit( Reference<XControl> (), ::com::sun::star::awt::MouseEvent() );
324     return 0L;
325 }
326 
327 //------------------------------------------------------------------------------
getSupportedServiceNames()328 StringSequence  OFormattedControl::getSupportedServiceNames() throw()
329 {
330     StringSequence aSupported = OBoundControl::getSupportedServiceNames();
331     aSupported.realloc(aSupported.getLength() + 1);
332 
333     ::rtl::OUString*pArray = aSupported.getArray();
334     pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_FORMATTEDFIELD;
335     return aSupported;
336 }
337 
338 //------------------------------------------------------------------------------
setDesignMode(sal_Bool bOn)339 void OFormattedControl::setDesignMode(sal_Bool bOn) throw ( ::com::sun::star::uno::RuntimeException)
340 {
341     OBoundControl::setDesignMode(bOn);
342 }
343 
344 /*************************************************************************/
DBG_NAME(OFormattedModel)345 DBG_NAME(OFormattedModel)
346 //------------------------------------------------------------------
347 void OFormattedModel::implConstruct()
348 {
349     // members
350     m_bOriginalNumeric = sal_False;
351     m_bNumeric = sal_False;
352     m_xOriginalFormatter = NULL;
353     m_nKeyType = NumberFormat::UNDEFINED;
354     m_aNullDate = DBTypeConversion::getStandardDate();
355     m_nFieldType =  DataType::OTHER;
356 
357     // default our formats supplier
358     increment(m_refCount);
359     setPropertyToDefaultByHandle(PROPERTY_ID_FORMATSSUPPLIER);
360     decrement(m_refCount);
361 
362     startAggregatePropertyListening( PROPERTY_FORMATKEY );
363     startAggregatePropertyListening( PROPERTY_FORMATSSUPPLIER );
364 }
365 
366 //------------------------------------------------------------------
OFormattedModel(const Reference<XMultiServiceFactory> & _rxFactory)367 OFormattedModel::OFormattedModel(const Reference<XMultiServiceFactory>& _rxFactory)
368     :OEditBaseModel(_rxFactory, VCL_CONTROLMODEL_FORMATTEDFIELD, FRM_SUN_CONTROL_FORMATTEDFIELD, sal_True, sal_True )
369                             // use the old control name for compytibility reasons
370     ,OErrorBroadcaster( OComponentHelper::rBHelper )
371 {
372     DBG_CTOR(OFormattedModel, NULL);
373 
374     implConstruct();
375 
376     m_nClassId = FormComponentType::TEXTFIELD;
377     initValueProperty( PROPERTY_EFFECTIVE_VALUE, PROPERTY_ID_EFFECTIVE_VALUE );
378 }
379 
380 //------------------------------------------------------------------
OFormattedModel(const OFormattedModel * _pOriginal,const Reference<XMultiServiceFactory> & _rxFactory)381 OFormattedModel::OFormattedModel( const OFormattedModel* _pOriginal, const Reference< XMultiServiceFactory >& _rxFactory )
382     :OEditBaseModel( _pOriginal, _rxFactory )
383     ,OErrorBroadcaster( OComponentHelper::rBHelper )
384 {
385     DBG_CTOR(OFormattedModel, NULL);
386 
387     implConstruct();
388 }
389 
390 //------------------------------------------------------------------------------
~OFormattedModel()391 OFormattedModel::~OFormattedModel()
392 {
393     DBG_DTOR(OFormattedModel, NULL);
394 }
395 
396 // XCloneable
397 //------------------------------------------------------------------------------
IMPLEMENT_DEFAULT_CLONING(OFormattedModel)398 IMPLEMENT_DEFAULT_CLONING( OFormattedModel )
399 
400 //------------------------------------------------------------------------------
401 void SAL_CALL OFormattedModel::disposing()
402 {
403     OErrorBroadcaster::disposing();
404     OEditBaseModel::disposing();
405 }
406 
407 // XServiceInfo
408 //------------------------------------------------------------------------------
getSupportedServiceNames()409 StringSequence OFormattedModel::getSupportedServiceNames() throw()
410 {
411     StringSequence aSupported = OEditBaseModel::getSupportedServiceNames();
412 
413     sal_Int32 nOldLen = aSupported.getLength();
414     aSupported.realloc( nOldLen + 8 );
415     ::rtl::OUString* pStoreTo = aSupported.getArray() + nOldLen;
416 
417     *pStoreTo++ = BINDABLE_CONTROL_MODEL;
418     *pStoreTo++ = DATA_AWARE_CONTROL_MODEL;
419     *pStoreTo++ = VALIDATABLE_CONTROL_MODEL;
420 
421     *pStoreTo++ = BINDABLE_DATA_AWARE_CONTROL_MODEL;
422     *pStoreTo++ = VALIDATABLE_BINDABLE_CONTROL_MODEL;
423 
424     *pStoreTo++ = FRM_SUN_COMPONENT_FORMATTEDFIELD;
425     *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_FORMATTEDFIELD;
426     *pStoreTo++ = BINDABLE_DATABASE_FORMATTED_FIELD;
427 
428     return aSupported;
429 }
430 
431 // XAggregation
432 //------------------------------------------------------------------------------
queryAggregation(const Type & _rType)433 Any SAL_CALL OFormattedModel::queryAggregation(const Type& _rType) throw(RuntimeException)
434 {
435     Any aReturn = OEditBaseModel::queryAggregation( _rType );
436     return aReturn.hasValue() ? aReturn : OErrorBroadcaster::queryInterface( _rType );
437 }
438 
439 // XTypeProvider
440 //------------------------------------------------------------------------------
_getTypes()441 Sequence< Type > OFormattedModel::_getTypes()
442 {
443     return ::comphelper::concatSequences(
444         OEditBaseModel::_getTypes(),
445         OErrorBroadcaster::getTypes()
446     );
447 }
448 
449 // XPersistObject
450 //------------------------------------------------------------------------------
getServiceName()451 ::rtl::OUString SAL_CALL OFormattedModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException)
452 {
453     return ::rtl::OUString(FRM_COMPONENT_EDIT);
454 }
455 
456 // XPropertySet
457 //------------------------------------------------------------------------------
describeFixedProperties(Sequence<Property> & _rProps) const458 void OFormattedModel::describeFixedProperties( Sequence< Property >& _rProps ) const
459 {
460     BEGIN_DESCRIBE_PROPERTIES( 3, OEditBaseModel )
461         DECL_BOOL_PROP1(EMPTY_IS_NULL,                          BOUND);
462         DECL_PROP1(TABINDEX,            sal_Int16,              BOUND);
463         DECL_BOOL_PROP2(FILTERPROPOSAL,                         BOUND, MAYBEDEFAULT);
464     END_DESCRIBE_PROPERTIES();
465 }
466 
467 //------------------------------------------------------------------------------
describeAggregateProperties(Sequence<Property> & _rAggregateProps) const468 void OFormattedModel::describeAggregateProperties( Sequence< Property >& _rAggregateProps ) const
469 {
470     OEditBaseModel::describeAggregateProperties( _rAggregateProps );
471 
472     // TreatAsNumeric nicht transient : wir wollen es an der UI anbinden (ist noetig, um dem EffectiveDefault
473     // - der kann Text oder Zahl sein - einen Sinn zu geben)
474     ModifyPropertyAttributes(_rAggregateProps, PROPERTY_TREATASNUMERIC, 0, PropertyAttribute::TRANSIENT);
475     // same for FormatKey
476     // (though the paragraph above for the TreatAsNumeric does not hold anymore - we do not have an UI for this.
477     // But we have for the format key ...)
478     // 25.06.2001 - 87862 - frank.schoenheit@sun.com
479     ModifyPropertyAttributes(_rAggregateProps, PROPERTY_FORMATKEY, 0, PropertyAttribute::TRANSIENT);
480 
481     RemoveProperty(_rAggregateProps, PROPERTY_STRICTFORMAT);
482         // no strict format property for formatted fields: it does not make sense, 'cause
483         // there is no general way to decide which characters/sub strings are allowed during the input of an
484         // arbitraryly formatted control
485         // 81441 - 12/07/00 - FS
486 }
487 
488 //------------------------------------------------------------------------------
getFastPropertyValue(Any & rValue,sal_Int32 nHandle) const489 void OFormattedModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const
490 {
491     OEditBaseModel::getFastPropertyValue(rValue, nHandle);
492 }
493 
494 //------------------------------------------------------------------------------
setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any & rValue)495 void OFormattedModel::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any& rValue) throw ( ::com::sun::star::uno::Exception)
496 {
497     OEditBaseModel::setFastPropertyValue_NoBroadcast(nHandle, rValue);
498 }
499 
500 //------------------------------------------------------------------------------
convertFastPropertyValue(Any & rConvertedValue,Any & rOldValue,sal_Int32 nHandle,const Any & rValue)501 sal_Bool OFormattedModel::convertFastPropertyValue(Any& rConvertedValue, Any& rOldValue, sal_Int32 nHandle, const Any& rValue)
502                                                         throw( IllegalArgumentException )
503 {
504     return OEditBaseModel::convertFastPropertyValue(rConvertedValue, rOldValue, nHandle, rValue);
505 }
506 
507 //------------------------------------------------------------------------------
setPropertyToDefaultByHandle(sal_Int32 nHandle)508 void OFormattedModel::setPropertyToDefaultByHandle(sal_Int32 nHandle)
509 {
510     if (nHandle == PROPERTY_ID_FORMATSSUPPLIER)
511     {
512         Reference<XNumberFormatsSupplier>  xSupplier = calcDefaultFormatsSupplier();
513         DBG_ASSERT(m_xAggregateSet.is(), "OFormattedModel::setPropertyToDefaultByHandle(FORMATSSUPPLIER) : have no aggregate !");
514         if (m_xAggregateSet.is())
515             m_xAggregateSet->setPropertyValue(PROPERTY_FORMATSSUPPLIER, makeAny(xSupplier));
516     }
517     else
518         OEditBaseModel::setPropertyToDefaultByHandle(nHandle);
519 }
520 
521 //------------------------------------------------------------------------------
setPropertyToDefault(const::rtl::OUString & aPropertyName)522 void OFormattedModel::setPropertyToDefault(const ::rtl::OUString& aPropertyName) throw( com::sun::star::beans::UnknownPropertyException, RuntimeException )
523 {
524     OPropertyArrayAggregationHelper& rPH = m_aPropertyBagHelper.getInfoHelper();
525     sal_Int32 nHandle = rPH.getHandleByName( aPropertyName );
526 
527     if (nHandle == PROPERTY_ID_FORMATSSUPPLIER)
528         setPropertyToDefaultByHandle(PROPERTY_ID_FORMATSSUPPLIER);
529     else
530         OEditBaseModel::setPropertyToDefault(aPropertyName);
531 }
532 
533 //------------------------------------------------------------------------------
getPropertyDefaultByHandle(sal_Int32 nHandle) const534 Any OFormattedModel::getPropertyDefaultByHandle( sal_Int32 nHandle ) const
535 {
536     if (nHandle == PROPERTY_ID_FORMATSSUPPLIER)
537     {
538         Reference<XNumberFormatsSupplier>  xSupplier = calcDefaultFormatsSupplier();
539         return makeAny(xSupplier);
540     }
541     else
542         return OEditBaseModel::getPropertyDefaultByHandle(nHandle);
543 }
544 
545 //------------------------------------------------------------------------------
getPropertyDefault(const::rtl::OUString & aPropertyName)546 Any SAL_CALL OFormattedModel::getPropertyDefault( const ::rtl::OUString& aPropertyName ) throw( com::sun::star::beans::UnknownPropertyException, RuntimeException )
547 {
548     OPropertyArrayAggregationHelper& rPH = m_aPropertyBagHelper.getInfoHelper();
549     sal_Int32 nHandle = rPH.getHandleByName( aPropertyName );
550 
551     if (nHandle == PROPERTY_ID_FORMATSSUPPLIER)
552         return getPropertyDefaultByHandle(PROPERTY_ID_FORMATSSUPPLIER);
553     else
554         return OEditBaseModel::getPropertyDefault(aPropertyName);
555 }
556 
557 //------------------------------------------------------------------------------
_propertyChanged(const com::sun::star::beans::PropertyChangeEvent & evt)558 void OFormattedModel::_propertyChanged( const com::sun::star::beans::PropertyChangeEvent& evt ) throw(RuntimeException)
559 {
560     // TODO: check how this works with external bindings
561 
562     OSL_ENSURE( evt.Source == m_xAggregateSet, "OFormattedModel::_propertyChanged: where did this come from?" );
563     if ( evt.Source == m_xAggregateSet )
564     {
565         Reference< XPropertySet > xSourceSet( evt.Source, UNO_QUERY );
566         if ( evt.PropertyName.equals( PROPERTY_FORMATKEY ) )
567         {
568             if ( evt.NewValue.getValueType().getTypeClass() == TypeClass_LONG )
569             {
570                 try
571                 {
572                     ::osl::MutexGuard aGuard( m_aMutex );
573 
574                     Reference<XNumberFormatsSupplier> xSupplier( calcFormatsSupplier() );
575                     m_nKeyType  = getNumberFormatType(xSupplier->getNumberFormats(), getINT32( evt.NewValue ) );
576 
577                     // as m_aSaveValue (which is used by commitControlValueToDbColumn) is format dependent we have
578                     // to recalc it, which is done by translateDbColumnToControlValue
579                     if ( m_xColumn.is() && m_xAggregateFastSet.is()  && !m_xCursor->isBeforeFirst() && !m_xCursor->isAfterLast())
580                     {
581                         setControlValue( translateDbColumnToControlValue(), eOther );
582                     }
583 
584                     // if we're connected to an external value binding, then re-calculate the type
585                     // used to exchange the value - it depends on the format, too
586                     if ( hasExternalValueBinding() )
587                     {
588                         calculateExternalValueType();
589                     }
590                 }
591                 catch(Exception&)
592                 {
593                 }
594             }
595             return;
596         }
597 
598         if ( evt.PropertyName.equals( PROPERTY_FORMATSSUPPLIER ) )
599         {
600             updateFormatterNullDate();
601             return;
602         }
603 
604         OBoundControlModel::_propertyChanged( evt );
605     }
606 }
607 
608 //------------------------------------------------------------------------------
updateFormatterNullDate()609 void OFormattedModel::updateFormatterNullDate()
610 {
611     // calc the current NULL date
612     Reference< XNumberFormatsSupplier > xSupplier( calcFormatsSupplier() );
613     if ( xSupplier.is() )
614         xSupplier->getNumberFormatSettings()->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "NullDate" ) ) ) >>= m_aNullDate;
615 }
616 
617 //------------------------------------------------------------------------------
calcFormatsSupplier() const618 Reference< XNumberFormatsSupplier > OFormattedModel::calcFormatsSupplier() const
619 {
620     Reference<XNumberFormatsSupplier>  xSupplier;
621 
622     DBG_ASSERT(m_xAggregateSet.is(), "OFormattedModel::calcFormatsSupplier : have no aggregate !");
623     // hat mein aggregiertes Model einen FormatSupplier ?
624     if( m_xAggregateSet.is() )
625         m_xAggregateSet->getPropertyValue(PROPERTY_FORMATSSUPPLIER) >>= xSupplier;
626 
627     if (!xSupplier.is())
628         // check if my parent form has a supplier
629         xSupplier = calcFormFormatsSupplier();
630 
631     if (!xSupplier.is())
632         xSupplier = calcDefaultFormatsSupplier();
633 
634     DBG_ASSERT(xSupplier.is(), "OFormattedModel::calcFormatsSupplier : no supplier !");
635         // jetzt sollte aber einer da sein
636     return xSupplier;
637 }
638 
639 //------------------------------------------------------------------------------
calcFormFormatsSupplier() const640 Reference<XNumberFormatsSupplier>  OFormattedModel::calcFormFormatsSupplier() const
641 {
642     Reference<XChild>  xMe;
643     query_interface(static_cast<XWeak*>(const_cast<OFormattedModel*>(this)), xMe);
644     // damit stellen wir sicher, dass wir auch fuer den Fall der Aggregation das richtige
645     // Objekt bekommen
646     DBG_ASSERT(xMe.is(), "OFormattedModel::calcFormFormatsSupplier : I should have a content interface !");
647 
648     // jetzt durchhangeln nach oben, bis wir auf eine starform treffen (angefangen mit meinem eigenen Parent)
649     Reference<XChild>  xParent(xMe->getParent(), UNO_QUERY);
650     Reference<XForm>  xNextParentForm(xParent, UNO_QUERY);
651     while (!xNextParentForm.is() && xParent.is())
652     {
653         xParent         = xParent.query( xParent->getParent() );
654         xNextParentForm = xNextParentForm.query( xParent );
655     }
656 
657     if (!xNextParentForm.is())
658     {
659         DBG_ERROR("OFormattedModel::calcFormFormatsSupplier : have no ancestor which is a form !");
660         return NULL;
661     }
662 
663     // den FormatSupplier von meinem Vorfahren (falls der einen hat)
664     Reference< XRowSet > xRowSet( xNextParentForm, UNO_QUERY );
665     Reference< XNumberFormatsSupplier > xSupplier;
666     if (xRowSet.is())
667         xSupplier = getNumberFormats( getConnection(xRowSet), sal_True, getContext().getLegacyServiceFactory() );
668     return xSupplier;
669 }
670 
671 //------------------------------------------------------------------------------
calcDefaultFormatsSupplier() const672 Reference< XNumberFormatsSupplier > OFormattedModel::calcDefaultFormatsSupplier() const
673 {
674     return StandardFormatsSupplier::get( getContext().getLegacyServiceFactory() );
675 }
676 
677 // XBoundComponent
678 //------------------------------------------------------------------------------
loaded(const EventObject & rEvent)679 void OFormattedModel::loaded(const EventObject& rEvent) throw ( ::com::sun::star::uno::RuntimeException)
680 {
681     // HACK : our onConnectedDbColumn accesses our NumberFormatter which locks the solar mutex (as it doesn't have
682     // an own one). To prevent deadlocks with other threads which may request a property from us in an
683     // UI-triggered action (e.g. an tooltip) we lock the solar mutex _here_ before our base class locks
684     // it's own muext (which is used for property requests)
685     // alternative a): we use two mutexes, one which is passed to the OPropertysetHelper and used for
686     // property requests and one for our own code. This would need a lot of code rewriting
687     // alternative b): The NumberFormatter has to be really threadsafe (with an own mutex), which is
688     // the only "clean" solution for me.
689     // FS - 69603 - 02.11.99
690 
691     ::vos::OGuard aGuard(Application::GetSolarMutex());
692     OEditBaseModel::loaded(rEvent);
693 }
694 
695 //------------------------------------------------------------------------------
onConnectedDbColumn(const Reference<XInterface> & _rxForm)696 void OFormattedModel::onConnectedDbColumn( const Reference< XInterface >& _rxForm )
697 {
698     m_xOriginalFormatter = NULL;
699 
700     // get some properties of the field
701     m_nFieldType = DataType::OTHER;
702     Reference<XPropertySet> xField = getField();
703     if ( xField.is() )
704         xField->getPropertyValue( PROPERTY_FIELDTYPE ) >>= m_nFieldType;
705 
706     sal_Int32 nFormatKey = 0;
707 
708     DBG_ASSERT(m_xAggregateSet.is(), "OFormattedModel::onConnectedDbColumn : have no aggregate !");
709     if (m_xAggregateSet.is())
710     {   // all the following doesn't make any sense if we have no aggregate ...
711         Any aSupplier = m_xAggregateSet->getPropertyValue(PROPERTY_FORMATSSUPPLIER);
712         DBG_ASSERT( aSupplier.hasValue(), "OFormattedModel::onConnectedDbColumn : invalid property value !" );
713         // das sollte im Constructor oder im read auf was richtiges gesetzt worden sein
714 
715         Any aFmtKey = m_xAggregateSet->getPropertyValue(PROPERTY_FORMATKEY);
716         if ( !(aFmtKey >>= nFormatKey ) )
717         {   // nobody gave us a format to use. So we examine the field we're bound to for a
718             // format key, and use it ourself, too
719             sal_Int32 nType = DataType::VARCHAR;
720             if (xField.is())
721             {
722                 aFmtKey = xField->getPropertyValue(PROPERTY_FORMATKEY);
723                 xField->getPropertyValue(PROPERTY_FIELDTYPE) >>= nType ;
724             }
725 
726             Reference<XNumberFormatsSupplier>  xSupplier = calcFormFormatsSupplier();
727             DBG_ASSERT(xSupplier.is(), "OFormattedModel::onConnectedDbColumn : bound to a field but no parent with a formatter ? how this ?");
728             if (xSupplier.is())
729             {
730                 m_bOriginalNumeric = getBOOL(getPropertyValue(PROPERTY_TREATASNUMERIC));
731 
732                 if (!aFmtKey.hasValue())
733                 {   // we aren't bound to a field (or this field's format is invalid)
734                     // -> determine the standard text (or numeric) format of the supplier
735                     Reference<XNumberFormatTypes>  xTypes(xSupplier->getNumberFormats(), UNO_QUERY);
736                     if (xTypes.is())
737                     {
738                         Locale aApplicationLocale = Application::GetSettings().GetUILocale();
739 
740                         if (m_bOriginalNumeric)
741                             aFmtKey <<= (sal_Int32)xTypes->getStandardFormat(NumberFormat::NUMBER, aApplicationLocale);
742                         else
743                             aFmtKey <<= (sal_Int32)xTypes->getStandardFormat(NumberFormat::TEXT, aApplicationLocale);
744                     }
745                 }
746 
747                 aSupplier >>= m_xOriginalFormatter;
748                 m_xAggregateSet->setPropertyValue(PROPERTY_FORMATSSUPPLIER, makeAny(xSupplier));
749                 m_xAggregateSet->setPropertyValue(PROPERTY_FORMATKEY, aFmtKey);
750 
751                 // das Numeric-Flag an mein gebundenes Feld anpassen
752                 if (xField.is())
753                 {
754                     m_bNumeric = sal_False;
755                     switch (nType)
756                     {
757                         case DataType::BIT:
758                         case DataType::BOOLEAN:
759                         case DataType::TINYINT:
760                         case DataType::SMALLINT:
761                         case DataType::INTEGER:
762                         case DataType::BIGINT:
763                         case DataType::FLOAT:
764                         case DataType::REAL:
765                         case DataType::DOUBLE:
766                         case DataType::NUMERIC:
767                         case DataType::DECIMAL:
768                         case DataType::DATE:
769                         case DataType::TIME:
770                         case DataType::TIMESTAMP:
771                             m_bNumeric = sal_True;
772                             break;
773                     }
774                 }
775                 else
776                     m_bNumeric = m_bOriginalNumeric;
777 
778                 setPropertyValue(PROPERTY_TREATASNUMERIC, makeAny((sal_Bool)m_bNumeric));
779 
780                 OSL_VERIFY( aFmtKey >>= nFormatKey );
781             }
782         }
783     }
784 
785     Reference<XNumberFormatsSupplier>  xSupplier = calcFormatsSupplier();
786     m_bNumeric = getBOOL( getPropertyValue( PROPERTY_TREATASNUMERIC ) );
787     m_nKeyType  = getNumberFormatType( xSupplier->getNumberFormats(), nFormatKey );
788     xSupplier->getNumberFormatSettings()->getPropertyValue( ::rtl::OUString::createFromAscii("NullDate") ) >>= m_aNullDate;
789 
790     OEditBaseModel::onConnectedDbColumn( _rxForm );
791 }
792 
793 //------------------------------------------------------------------------------
onDisconnectedDbColumn()794 void OFormattedModel::onDisconnectedDbColumn()
795 {
796     OEditBaseModel::onDisconnectedDbColumn();
797     if (m_xOriginalFormatter.is())
798     {   // unser aggregiertes Model hatte keinerlei Format-Informationen
799         m_xAggregateSet->setPropertyValue(PROPERTY_FORMATSSUPPLIER, makeAny(m_xOriginalFormatter));
800         m_xAggregateSet->setPropertyValue(PROPERTY_FORMATKEY, Any());
801         setPropertyValue(PROPERTY_TREATASNUMERIC, makeAny((sal_Bool)m_bOriginalNumeric));
802         m_xOriginalFormatter = NULL;
803     }
804 
805     m_nFieldType = DataType::OTHER;
806     m_nKeyType   = NumberFormat::UNDEFINED;
807     m_aNullDate  = DBTypeConversion::getStandardDate();
808 }
809 
810 //------------------------------------------------------------------------------
write(const Reference<XObjectOutputStream> & _rxOutStream)811 void OFormattedModel::write(const Reference<XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
812 {
813     OEditBaseModel::write(_rxOutStream);
814     _rxOutStream->writeShort(0x0003);
815 
816     DBG_ASSERT(m_xAggregateSet.is(), "OFormattedModel::write : have no aggregate !");
817 
818     // mein Format (evtl. void) in ein persistentes Format bringen (der Supplier zusammen mit dem Key ist es zwar auch,
819     // aber deswegen muessen wir ja nicht gleich den ganzen Supplier speichern, das waere ein klein wenig Overhead ;)
820 
821         Reference<XNumberFormatsSupplier>  xSupplier;
822         Any aFmtKey;
823     sal_Bool bVoidKey = sal_True;
824     if (m_xAggregateSet.is())
825     {
826         Any aSupplier = m_xAggregateSet->getPropertyValue(PROPERTY_FORMATSSUPPLIER);
827         if (aSupplier.getValueType().getTypeClass() != TypeClass_VOID)
828         {
829             OSL_VERIFY( aSupplier >>= xSupplier );
830         }
831 
832         aFmtKey = m_xAggregateSet->getPropertyValue(PROPERTY_FORMATKEY);
833         bVoidKey = (!xSupplier.is() || !aFmtKey.hasValue()) || (isLoaded() && m_xOriginalFormatter.is());
834             // (kein Fomatter und/oder Key) oder (loaded und faked Formatter)
835     }
836 
837     _rxOutStream->writeBoolean(!bVoidKey);
838     if (!bVoidKey)
839     {
840         // aus dem FormatKey und dem Formatter persistente Angaben basteln
841 
842         Any aKey = m_xAggregateSet->getPropertyValue(PROPERTY_FORMATKEY);
843         sal_Int32 nKey = aKey.hasValue() ? getINT32(aKey) : 0;
844 
845         Reference<XNumberFormats>  xFormats = xSupplier->getNumberFormats();
846 
847         ::rtl::OUString         sFormatDescription;
848         LanguageType    eFormatLanguage = LANGUAGE_DONTKNOW;
849 
850         static const ::rtl::OUString s_aLocaleProp = ::rtl::OUString::createFromAscii("Locale");
851         Reference<com::sun::star::beans::XPropertySet>  xFormat = xFormats->getByKey(nKey);
852         if (hasProperty(s_aLocaleProp, xFormat))
853         {
854             Any aLocale = xFormat->getPropertyValue(s_aLocaleProp);
855             DBG_ASSERT(isA(aLocale, static_cast<Locale*>(NULL)), "OFormattedModel::write : invalid language property !");
856             if (isA(aLocale, static_cast<Locale*>(NULL)))
857             {
858                 Locale* pLocale = (Locale*)aLocale.getValue();
859                 eFormatLanguage = MsLangId::convertLocaleToLanguage( *pLocale );
860             }
861         }
862 
863         static const ::rtl::OUString s_aFormatStringProp = ::rtl::OUString::createFromAscii("FormatString");
864         if (hasProperty(s_aFormatStringProp, xFormat))
865             xFormat->getPropertyValue(s_aFormatStringProp) >>= sFormatDescription;
866 
867         _rxOutStream->writeUTF(sFormatDescription);
868         _rxOutStream->writeLong((sal_Int32)eFormatLanguage);
869     }
870 
871     // version 2 : write the properties common to all OEditBaseModels
872     writeCommonEditProperties(_rxOutStream);
873 
874     // version 3 : write the effective value property of the aggregate
875     // Due to a bug within the UnoControlFormattedFieldModel implementation (our default aggregate) this props value isn't correctly read
876     // and this can't be corrected without being incompatible.
877     // so we have our own handling.
878 
879     // and to be a little bit more compatible we make the following section skippable
880     {
881         Reference< XDataOutputStream > xOut(_rxOutStream, UNO_QUERY);
882         OStreamSection aDownCompat(xOut);
883 
884         // a sub version within the skippable block
885         _rxOutStream->writeShort(0x0000);
886 
887         // version 0: the effective value of the aggregate
888                 Any aEffectiveValue;
889         if (m_xAggregateSet.is())
890         {
891             try { aEffectiveValue = m_xAggregateSet->getPropertyValue(PROPERTY_EFFECTIVE_VALUE); } catch(Exception&) { }
892         }
893 
894         {
895             OStreamSection aDownCompat2(xOut);
896             switch (aEffectiveValue.getValueType().getTypeClass())
897             {
898                 case TypeClass_STRING:
899                     _rxOutStream->writeShort(0x0000);
900                     _rxOutStream->writeUTF(::comphelper::getString(aEffectiveValue));
901                     break;
902                 case TypeClass_DOUBLE:
903                     _rxOutStream->writeShort(0x0001);
904                     _rxOutStream->writeDouble(::comphelper::getDouble(aEffectiveValue));
905                     break;
906                 default:    // void and all unknown states
907                     DBG_ASSERT(!aEffectiveValue.hasValue(), "FmXFormattedModel::write : unknown property value type !");
908                     _rxOutStream->writeShort(0x0002);
909                     break;
910             }
911         }
912     }
913 }
914 
915 //------------------------------------------------------------------------------
read(const Reference<XObjectInputStream> & _rxInStream)916 void OFormattedModel::read(const Reference<XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
917 {
918     OEditBaseModel::read(_rxInStream);
919     sal_uInt16 nVersion = _rxInStream->readShort();
920 
921     Reference<XNumberFormatsSupplier>  xSupplier;
922     sal_Int32 nKey = -1;
923     switch (nVersion)
924     {
925         case 0x0001 :
926         case 0x0002 :
927         case 0x0003 :
928         {
929             sal_Bool bNonVoidKey = _rxInStream->readBoolean();
930             if (bNonVoidKey)
931             {
932                 // den String und die Language lesen ....
933                 ::rtl::OUString sFormatDescription = _rxInStream->readUTF();
934                 LanguageType eDescriptionLanguage = (LanguageType)_rxInStream->readLong();
935 
936                 // und daraus von einem Formatter zu einem Key zusammenwuerfeln lassen ...
937                 xSupplier = calcFormatsSupplier();
938                     // calcFormatsSupplier nimmt erst den vom Model, dann einen von der starform, dann einen ganz neuen ....
939                 Reference<XNumberFormats>  xFormats = xSupplier->getNumberFormats();
940 
941                 if (xFormats.is())
942                 {
943                     Locale aDescriptionLanguage( MsLangId::convertLanguageToLocale(eDescriptionLanguage));
944 
945                     nKey = xFormats->queryKey(sFormatDescription, aDescriptionLanguage, sal_False);
946                     if (nKey == (sal_Int32)-1)
947                     {   // noch nicht vorhanden in meinem Formatter ...
948                         nKey = xFormats->addNew(sFormatDescription, aDescriptionLanguage);
949                     }
950                 }
951             }
952             if ((nVersion == 0x0002) || (nVersion == 0x0003))
953                 readCommonEditProperties(_rxInStream);
954 
955             if (nVersion == 0x0003)
956             {   // since version 3 there is a "skippable" block at this position
957                 Reference< XDataInputStream > xIn(_rxInStream, UNO_QUERY);
958                 OStreamSection aDownCompat(xIn);
959 
960                 sal_Int16 nSubVersion = _rxInStream->readShort();
961                 (void)nSubVersion;
962 
963                 // version 0 and higher : the "effective value" property
964                 Any aEffectiveValue;
965                 {
966                     OStreamSection aDownCompat2(xIn);
967                     switch (_rxInStream->readShort())
968                     {
969                         case 0: // String
970                             aEffectiveValue <<= _rxInStream->readUTF();
971                             break;
972                         case 1: // double
973                             aEffectiveValue <<= (double)_rxInStream->readDouble();
974                             break;
975                         case 2:
976                             break;
977                         case 3:
978                             DBG_ERROR("FmXFormattedModel::read : unknown effective value type !");
979                     }
980                 }
981 
982                 // this property is only to be set if we have no control source : in all other cases the base class did a
983                 // reset after it's read and this set the effective value to a default value
984                 if ( m_xAggregateSet.is() && ( getControlSource().getLength() == 0 ) )
985                 {
986                     try
987                     {
988                         m_xAggregateSet->setPropertyValue(PROPERTY_EFFECTIVE_VALUE, aEffectiveValue);
989                     }
990                     catch(Exception&)
991                     {
992                     }
993                 }
994             }
995         }
996         break;
997         default :
998             DBG_ERROR("OFormattedModel::read : unknown version !");
999             // dann bleibt das Format des aggregierten Sets, wie es bei der Erzeugung ist : void
1000             defaultCommonEditProperties();
1001             break;
1002     }
1003 
1004     if ((nKey != -1) && m_xAggregateSet.is())
1005     {
1006                 m_xAggregateSet->setPropertyValue(PROPERTY_FORMATSSUPPLIER, makeAny(xSupplier));
1007                 m_xAggregateSet->setPropertyValue(PROPERTY_FORMATKEY, makeAny((sal_Int32)nKey));
1008     }
1009     else
1010     {
1011         setPropertyToDefault(PROPERTY_FORMATSSUPPLIER);
1012         setPropertyToDefault(PROPERTY_FORMATKEY);
1013     }
1014 }
1015 
1016 //------------------------------------------------------------------------------
getPersistenceFlags() const1017 sal_uInt16 OFormattedModel::getPersistenceFlags() const
1018 {
1019     return (OEditBaseModel::getPersistenceFlags() & ~PF_HANDLE_COMMON_PROPS);
1020     // a) we do our own call to writeCommonEditProperties
1021 }
1022 
1023 //------------------------------------------------------------------------------
commitControlValueToDbColumn(bool)1024 sal_Bool OFormattedModel::commitControlValueToDbColumn( bool /*_bPostReset*/ )
1025 {
1026     Any aControlValue( m_xAggregateFastSet->getFastPropertyValue( getValuePropertyAggHandle() ) );
1027     if ( aControlValue != m_aSaveValue )
1028     {
1029         // Leerstring + EmptyIsNull = void
1030         if  (   !aControlValue.hasValue()
1031             ||  (   ( aControlValue.getValueType().getTypeClass() == TypeClass_STRING )
1032                 &&  ( getString( aControlValue ).getLength() == 0 )
1033                 &&  m_bEmptyIsNull
1034                 )
1035             )
1036             m_xColumnUpdate->updateNull();
1037         else
1038         {
1039             try
1040             {
1041                 double f = 0.0;
1042                 if ( aControlValue.getValueType().getTypeClass() == TypeClass_DOUBLE || (aControlValue >>= f)) // #i110323
1043                 {
1044                     DBTypeConversion::setValue( m_xColumnUpdate, m_aNullDate, getDouble( aControlValue ), m_nKeyType );
1045                 }
1046                 else
1047                 {
1048                     DBG_ASSERT( aControlValue.getValueType().getTypeClass() == TypeClass_STRING, "OFormattedModel::commitControlValueToDbColumn: invalud value type !" );
1049                     m_xColumnUpdate->updateString( getString( aControlValue ) );
1050                 }
1051             }
1052             catch(Exception&)
1053             {
1054                 return sal_False;
1055             }
1056         }
1057         m_aSaveValue = aControlValue;
1058     }
1059     return sal_True;
1060 }
1061 
1062 //------------------------------------------------------------------------------
onConnectedExternalValue()1063 void OFormattedModel::onConnectedExternalValue( )
1064 {
1065     OEditBaseModel::onConnectedExternalValue();
1066     updateFormatterNullDate();
1067 }
1068 
1069 //------------------------------------------------------------------------------
translateExternalValueToControlValue(const Any & _rExternalValue) const1070 Any OFormattedModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const
1071 {
1072     Any aControlValue;
1073     switch( _rExternalValue.getValueTypeClass() )
1074     {
1075     case TypeClass_VOID:
1076         break;
1077 
1078     case TypeClass_STRING:
1079         aControlValue = _rExternalValue;
1080         break;
1081 
1082     case TypeClass_BOOLEAN:
1083     {
1084         sal_Bool bExternalValue = sal_False;
1085         _rExternalValue >>= bExternalValue;
1086         aControlValue <<= (double)( bExternalValue ? 1 : 0 );
1087     }
1088     break;
1089 
1090     default:
1091     {
1092         if ( _rExternalValue.getValueType().equals( ::getCppuType( static_cast< UNODate* >( NULL ) ) ) )
1093         {
1094             UNODate aDate;
1095             _rExternalValue >>= aDate;
1096             aControlValue <<= DBTypeConversion::toDouble( aDate, m_aNullDate );
1097         }
1098         else if ( _rExternalValue.getValueType().equals( ::getCppuType( static_cast< UNOTime* >( NULL ) ) ) )
1099         {
1100             UNOTime aTime;
1101             _rExternalValue >>= aTime;
1102             aControlValue <<= DBTypeConversion::toDouble( aTime );
1103         }
1104         else if ( _rExternalValue.getValueType().equals( ::getCppuType( static_cast< UNODateTime* >( NULL ) ) ) )
1105         {
1106             UNODateTime aDateTime;
1107             _rExternalValue >>= aDateTime;
1108             aControlValue <<= DBTypeConversion::toDouble( aDateTime, m_aNullDate );
1109         }
1110         else
1111         {
1112             OSL_ENSURE( _rExternalValue.getValueTypeClass() == TypeClass_DOUBLE,
1113                 "OFormattedModel::translateExternalValueToControlValue: don't know how to translate this type!" );
1114             double fValue = 0;
1115             OSL_VERIFY( _rExternalValue >>= fValue );
1116             aControlValue <<= fValue;
1117         }
1118     }
1119     }
1120 
1121     return aControlValue;
1122 }
1123 
1124 //------------------------------------------------------------------------------
translateControlValueToExternalValue() const1125 Any OFormattedModel::translateControlValueToExternalValue( ) const
1126 {
1127     OSL_PRECOND( hasExternalValueBinding(),
1128         "OFormattedModel::translateControlValueToExternalValue: precondition not met!" );
1129 
1130     Any aControlValue( getControlValue() );
1131     if ( !aControlValue.hasValue() )
1132         return aControlValue;
1133 
1134     Any aExternalValue;
1135 
1136     // translate into the the external value type
1137     Type aExternalValueType( getExternalValueType() );
1138     switch ( aExternalValueType.getTypeClass() )
1139     {
1140     case TypeClass_STRING:
1141     {
1142         ::rtl::OUString sString;
1143         if ( aControlValue >>= sString )
1144         {
1145             aExternalValue <<= sString;
1146             break;
1147         }
1148     }
1149     // NO break here!
1150 
1151     case TypeClass_BOOLEAN:
1152     {
1153         double fValue = 0;
1154         OSL_VERIFY( aControlValue >>= fValue );
1155             // if this asserts ... well, the somebody set the TreatAsNumeric property to false,
1156             // and the control value is a string. This implies some weird misconfiguration
1157             // of the FormattedModel, so we won't care for it for the moment.
1158         aExternalValue <<= (sal_Bool)( fValue ? sal_True : sal_False );
1159     }
1160     break;
1161 
1162     default:
1163     {
1164         double fValue = 0;
1165         OSL_VERIFY( aControlValue >>= fValue );
1166             // if this asserts ... well, the somebody set the TreatAsNumeric property to false,
1167             // and the control value is a string. This implies some weird misconfiguration
1168             // of the FormattedModel, so we won't care for it for the moment.
1169 
1170         if ( aExternalValueType.equals( ::getCppuType( static_cast< UNODate* >( NULL ) ) ) )
1171         {
1172             aExternalValue <<= DBTypeConversion::toDate( fValue, m_aNullDate );
1173         }
1174         else if ( aExternalValueType.equals( ::getCppuType( static_cast< UNOTime* >( NULL ) ) ) )
1175         {
1176             aExternalValue <<= DBTypeConversion::toTime( fValue );
1177         }
1178         else if ( aExternalValueType.equals( ::getCppuType( static_cast< UNODateTime* >( NULL ) ) ) )
1179         {
1180             aExternalValue <<= DBTypeConversion::toDateTime( fValue, m_aNullDate );
1181         }
1182         else
1183         {
1184             OSL_ENSURE( aExternalValueType.equals( ::getCppuType( static_cast< double* >( NULL ) ) ),
1185                 "OFormattedModel::translateControlValueToExternalValue: don't know how to translate this type!" );
1186             aExternalValue <<= fValue;
1187         }
1188     }
1189     break;
1190     }
1191     return aExternalValue;
1192 }
1193 
1194 //------------------------------------------------------------------------------
translateDbColumnToControlValue()1195 Any OFormattedModel::translateDbColumnToControlValue()
1196 {
1197     if ( m_bNumeric )
1198         m_aSaveValue <<= DBTypeConversion::getValue( m_xColumn, m_aNullDate ); // #100056# OJ
1199     else
1200         m_aSaveValue <<= m_xColumn->getString();
1201 
1202     if ( m_xColumn->wasNull() )
1203         m_aSaveValue.clear();
1204 
1205     return m_aSaveValue;
1206 }
1207 
1208 // -----------------------------------------------------------------------------
getSupportedBindingTypes()1209 Sequence< Type > OFormattedModel::getSupportedBindingTypes()
1210 {
1211     ::std::list< Type > aTypes;
1212     aTypes.push_back( ::getCppuType( static_cast< double* >( NULL ) ) );
1213 
1214     switch ( m_nKeyType & ~NumberFormat::DEFINED )
1215     {
1216     case NumberFormat::DATE:
1217         aTypes.push_front(::getCppuType( static_cast< UNODate* >( NULL ) ) );
1218         break;
1219     case NumberFormat::TIME:
1220         aTypes.push_front(::getCppuType( static_cast< UNOTime* >( NULL ) ) );
1221         break;
1222     case NumberFormat::DATETIME:
1223         aTypes.push_front(::getCppuType( static_cast< UNODateTime* >( NULL ) ) );
1224         break;
1225     case NumberFormat::TEXT:
1226         aTypes.push_front(::getCppuType( static_cast< ::rtl::OUString* >( NULL ) ) );
1227         break;
1228     case NumberFormat::LOGICAL:
1229         aTypes.push_front(::getCppuType( static_cast< sal_Bool* >( NULL ) ) );
1230         break;
1231     }
1232 
1233     Sequence< Type > aTypesRet( aTypes.size() );
1234     ::std::copy( aTypes.begin(), aTypes.end(), aTypesRet.getArray() );
1235     return aTypesRet;
1236 }
1237 
1238 //------------------------------------------------------------------------------
getDefaultForReset() const1239 Any OFormattedModel::getDefaultForReset() const
1240 {
1241     return m_xAggregateSet->getPropertyValue( PROPERTY_EFFECTIVE_DEFAULT );
1242 }
1243 
1244 //------------------------------------------------------------------------------
resetNoBroadcast()1245 void OFormattedModel::resetNoBroadcast()
1246 {
1247     OEditBaseModel::resetNoBroadcast();
1248     m_aSaveValue.clear();
1249 }
1250 
1251 //.........................................................................
1252 }
1253 //.........................................................................
1254