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