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