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 //------------------------------------------------------------------
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 //------------------------------------------------------------------
130 StandardFormatsSupplier::~StandardFormatsSupplier()
131 {
132     ::utl::DesktopTerminationObserver::revokeTerminationListener( this );
133 
134     DELETEZ( m_pMyPrivateFormatter );
135 }
136 
137 //------------------------------------------------------------------
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 //------------------------------------------------------------------
171 bool StandardFormatsSupplier::queryTermination() const
172 {
173     return true;
174 }
175 
176 //------------------------------------------------------------------
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 //------------------------------------------------------------------
191 InterfaceRef SAL_CALL OFormattedControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory)
192 {
193 	return *(new OFormattedControl(_rxFactory));
194 }
195 
196 //------------------------------------------------------------------
197 Sequence<Type> OFormattedControl::_getTypes()
198 {
199 	return ::comphelper::concatSequences(
200 		OFormattedControl_BASE::getTypes(),
201 		OBoundControl::_getTypes()
202 	);
203 }
204 
205 //------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
251 void OFormattedControl::disposing(const EventObject& _rSource) throw(RuntimeException)
252 {
253 	OBoundControl::disposing(_rSource);
254 }
255 
256 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
339 void OFormattedControl::setDesignMode(sal_Bool bOn) throw ( ::com::sun::star::uno::RuntimeException)
340 {
341 	OBoundControl::setDesignMode(bOn);
342 }
343 
344 /*************************************************************************/
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 //------------------------------------------------------------------
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 //------------------------------------------------------------------
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 //------------------------------------------------------------------------------
391 OFormattedModel::~OFormattedModel()
392 {
393 	DBG_DTOR(OFormattedModel, NULL);
394 }
395 
396 // XCloneable
397 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
441 Sequence< Type > OFormattedModel::_getTypes()
442 {
443 	return ::comphelper::concatSequences(
444 		OEditBaseModel::_getTypes(),
445 		OErrorBroadcaster::getTypes()
446 	);
447 }
448 
449 // XPersistObject
450 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
458 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 //------------------------------------------------------------------------------
468 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 //------------------------------------------------------------------------------
489 void OFormattedModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const
490 {
491 	OEditBaseModel::getFastPropertyValue(rValue, nHandle);
492 }
493 
494 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
534 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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
618 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 //------------------------------------------------------------------------------
640 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 //------------------------------------------------------------------------------
672 Reference< XNumberFormatsSupplier > OFormattedModel::calcDefaultFormatsSupplier() const
673 {
674     return StandardFormatsSupplier::get( getContext().getLegacyServiceFactory() );
675 }
676 
677 // XBoundComponent
678 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
1017 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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
1063 void OFormattedModel::onConnectedExternalValue( )
1064 {
1065     OEditBaseModel::onConnectedExternalValue();
1066     updateFormatterNullDate();
1067 }
1068 
1069 //------------------------------------------------------------------------------
1070 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 //------------------------------------------------------------------------------
1125 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 //------------------------------------------------------------------------------
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 // -----------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
1239 Any OFormattedModel::getDefaultForReset() const
1240 {
1241     return m_xAggregateSet->getPropertyValue( PROPERTY_EFFECTIVE_DEFAULT );
1242 }
1243 
1244 //------------------------------------------------------------------------------
1245 void OFormattedModel::resetNoBroadcast()
1246 {
1247     OEditBaseModel::resetNoBroadcast();
1248     m_aSaveValue.clear();
1249 }
1250 
1251 //.........................................................................
1252 }
1253 //.........................................................................
1254