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