xref: /trunk/main/forms/source/component/Edit.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_forms.hxx"
30 
31 #include "Edit.hxx"
32 
33 #include <com/sun/star/uno/Type.hxx>
34 #include <com/sun/star/awt/XWindow.hpp>
35 #include <com/sun/star/container/XIndexAccess.hpp>
36 #include <com/sun/star/form/XSubmit.hpp>
37 #include <com/sun/star/util/NumberFormat.hpp>
38 #include <com/sun/star/sdbc/DataType.hpp>
39 #include <com/sun/star/awt/XVclWindowPeer.hpp>
40 
41 #include <vcl/svapp.hxx>
42 #include <tools/wintypes.hxx>
43 
44 #include <connectivity/dbtools.hxx>
45 #include <connectivity/formattedcolumnvalue.hxx>
46 #include <connectivity/dbconversion.hxx>
47 
48 #include <tools/diagnose_ex.h>
49 #include <tools/debug.hxx>
50 
51 #include <comphelper/container.hxx>
52 #include <comphelper/numbers.hxx>
53 
54 using namespace dbtools;
55 
56 //.........................................................................
57 namespace frm
58 {
59 using namespace ::com::sun::star::uno;
60 using namespace ::com::sun::star::sdb;
61 using namespace ::com::sun::star::sdbc;
62 using namespace ::com::sun::star::sdbcx;
63 using namespace ::com::sun::star::beans;
64 using namespace ::com::sun::star::container;
65 using namespace ::com::sun::star::form;
66 using namespace ::com::sun::star::awt;
67 using namespace ::com::sun::star::io;
68 using namespace ::com::sun::star::lang;
69 using namespace ::com::sun::star::util;
70 using namespace ::com::sun::star::form::binding;
71 
72 //------------------------------------------------------------------
73 InterfaceRef SAL_CALL OEditControl_CreateInstance(const Reference< XMultiServiceFactory > & _rxFactory)
74 {
75 	return *(new OEditControl(_rxFactory));
76 }
77 
78 //------------------------------------------------------------------------------
79 Sequence<Type> OEditControl::_getTypes()
80 {
81 	static Sequence<Type> aTypes;
82 	if (!aTypes.getLength())
83 	{
84 		// my two base classes
85 		aTypes = concatSequences(OBoundControl::_getTypes(), OEditControl_BASE::getTypes());
86 	}
87 	return aTypes;
88 }
89 
90 //------------------------------------------------------------------------------
91 Any SAL_CALL OEditControl::queryAggregation(const Type& _rType) throw (RuntimeException)
92 {
93 	Any aReturn = OBoundControl::queryAggregation(_rType);
94 	if (!aReturn.hasValue())
95 		aReturn = OEditControl_BASE::queryInterface(_rType);
96 
97 	return aReturn;
98 }
99 
100 DBG_NAME(OEditControl);
101 //------------------------------------------------------------------------------
102 OEditControl::OEditControl(const Reference<XMultiServiceFactory>& _rxFactory)
103 			   :OBoundControl( _rxFactory, FRM_SUN_CONTROL_RICHTEXTCONTROL )
104 			   ,m_aChangeListeners(m_aMutex)
105 			   ,m_nKeyEvent( 0 )
106 {
107 	DBG_CTOR(OEditControl,NULL);
108 
109 	increment(m_refCount);
110 	{
111 		Reference<XWindow>  xComp;
112 		if (query_aggregation(m_xAggregate, xComp))
113 		{
114 			xComp->addFocusListener(this);
115 			xComp->addKeyListener(this);
116 		}
117 	}
118 	decrement(m_refCount);
119 }
120 
121 //------------------------------------------------------------------------------
122 OEditControl::~OEditControl()
123 {
124 	if( m_nKeyEvent )
125 		Application::RemoveUserEvent( m_nKeyEvent );
126 
127 	if (!OComponentHelper::rBHelper.bDisposed)
128 	{
129 		acquire();
130 		dispose();
131 	}
132 
133 	DBG_DTOR(OEditControl,NULL);
134 }
135 
136 // XChangeBroadcaster
137 //------------------------------------------------------------------------------
138 void OEditControl::addChangeListener(const Reference<XChangeListener>& l) throw ( ::com::sun::star::uno::RuntimeException)
139 {
140 	m_aChangeListeners.addInterface( l );
141 }
142 
143 //------------------------------------------------------------------------------
144 void OEditControl::removeChangeListener(const Reference<XChangeListener>& l) throw ( ::com::sun::star::uno::RuntimeException)
145 {
146 	m_aChangeListeners.removeInterface( l );
147 }
148 
149 // OComponentHelper
150 //------------------------------------------------------------------------------
151 void OEditControl::disposing()
152 {
153 	OBoundControl::disposing();
154 
155 	EventObject aEvt(static_cast<XWeak*>(this));
156 	m_aChangeListeners.disposeAndClear(aEvt);
157 }
158 
159 // XServiceInfo
160 //------------------------------------------------------------------------------
161 StringSequence	OEditControl::getSupportedServiceNames() throw()
162 {
163 	StringSequence aSupported = OBoundControl::getSupportedServiceNames();
164 	aSupported.realloc(aSupported.getLength() + 1);
165 
166 	::rtl::OUString*pArray = aSupported.getArray();
167 	pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_TEXTFIELD;
168 	return aSupported;
169 }
170 
171 // XEventListener
172 //------------------------------------------------------------------------------
173 void OEditControl::disposing(const EventObject& Source) throw( RuntimeException )
174 {
175 	OBoundControl::disposing(Source);
176 }
177 
178 // XFocusListener
179 //------------------------------------------------------------------------------
180 void OEditControl::focusGained( const FocusEvent& /*e*/ ) throw ( ::com::sun::star::uno::RuntimeException)
181 {
182 	Reference<XPropertySet>  xSet(getModel(), UNO_QUERY);
183 	if (xSet.is())
184 		xSet->getPropertyValue( PROPERTY_TEXT ) >>= m_aHtmlChangeValue;
185 }
186 
187 //------------------------------------------------------------------------------
188 void OEditControl::focusLost( const FocusEvent& /*e*/ ) throw ( ::com::sun::star::uno::RuntimeException)
189 {
190 	Reference<XPropertySet>  xSet(getModel(), UNO_QUERY);
191 	if (xSet.is())
192 	{
193 		::rtl::OUString sNewHtmlChangeValue;
194 		xSet->getPropertyValue( PROPERTY_TEXT ) >>= sNewHtmlChangeValue;
195 		if( sNewHtmlChangeValue != m_aHtmlChangeValue )
196 		{
197 			EventObject aEvt( *this );
198             m_aChangeListeners.notifyEach( &XChangeListener::changed, aEvt );
199 		}
200 	}
201 }
202 
203 // XKeyListener
204 //------------------------------------------------------------------------------
205 void OEditControl::keyPressed(const ::com::sun::star::awt::KeyEvent& e) throw ( ::com::sun::star::uno::RuntimeException)
206 {
207 	if( e.KeyCode != KEY_RETURN || e.Modifiers != 0 )
208 		return;
209 
210 	// Steht das Control in einem Formular mit einer Submit-URL?
211 	Reference<XPropertySet>  xSet(getModel(), UNO_QUERY);
212 	if( !xSet.is() )
213 		return;
214 
215 	// nicht fuer multiline edits
216 	Any aTmp( xSet->getPropertyValue(PROPERTY_MULTILINE));
217 	if ((aTmp.getValueType().equals(::getBooleanCppuType())) && getBOOL(aTmp))
218 		return;
219 
220 	Reference<XFormComponent>  xFComp(xSet, UNO_QUERY);
221 	InterfaceRef  xParent = xFComp->getParent();
222 	if( !xParent.is() )
223 		return;
224 
225 	Reference<XPropertySet>  xFormSet(xParent, UNO_QUERY);
226 	if( !xFormSet.is() )
227 		return;
228 
229 	aTmp = xFormSet->getPropertyValue( PROPERTY_TARGET_URL );
230 	if (!aTmp.getValueType().equals(::getCppuType((const ::rtl::OUString*)NULL)) ||
231 		!getString(aTmp).getLength() )
232 		return;
233 
234 	Reference<XIndexAccess>  xElements(xParent, UNO_QUERY);
235 	sal_Int32 nCount = xElements->getCount();
236 	if( nCount > 1 )
237 	{
238 		Reference<XPropertySet>  xFCSet;
239 		for( sal_Int32 nIndex=0; nIndex < nCount; nIndex++ )
240 		{
241 			//	Any aElement(xElements->getByIndex(nIndex));
242 			xElements->getByIndex(nIndex) >>= xFCSet;
243 			OSL_ENSURE(xFCSet.is(),"OEditControl::keyPressed: No XPropertySet!");
244 
245 			if (hasProperty(PROPERTY_CLASSID, xFCSet) &&
246 				getINT16(xFCSet->getPropertyValue(PROPERTY_CLASSID)) == FormComponentType::TEXTFIELD)
247 			{
248 				// Noch ein weiteres Edit gefunden ==> dann nicht submitten
249 				if (xFCSet != xSet)
250 					return;
251 			}
252 		}
253 	}
254 
255 	// Da wir noch im Haender stehen, submit asynchron ausloesen
256 	if( m_nKeyEvent )
257 		Application::RemoveUserEvent( m_nKeyEvent );
258 	m_nKeyEvent = Application::PostUserEvent( LINK(this, OEditControl,OnKeyPressed) );
259 }
260 
261 //------------------------------------------------------------------------------
262 void OEditControl::keyReleased(const ::com::sun::star::awt::KeyEvent& /*e*/) throw ( ::com::sun::star::uno::RuntimeException)
263 {
264 }
265 
266 //------------------------------------------------------------------------------
267 IMPL_LINK(OEditControl, OnKeyPressed, void*, /*EMPTYARG*/)
268 {
269 	m_nKeyEvent = 0;
270 
271 	Reference<XFormComponent>  xFComp(getModel(), UNO_QUERY);
272 	InterfaceRef  xParent = xFComp->getParent();
273 	Reference<XSubmit>  xSubmit(xParent, UNO_QUERY);
274 	if (xSubmit.is())
275 		xSubmit->submit( Reference<XControl>(), ::com::sun::star::awt::MouseEvent() );
276 	return 0L;
277 }
278 
279 //------------------------------------------------------------------
280 void SAL_CALL OEditControl::createPeer( const Reference< XToolkit>& _rxToolkit, const Reference< XWindowPeer>& _rxParent ) throw ( RuntimeException )
281 {
282 	OBoundControl::createPeer(_rxToolkit, _rxParent);
283 }
284 
285 /*************************************************************************/
286 //------------------------------------------------------------------
287 InterfaceRef SAL_CALL OEditModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory)
288 {
289 	return *(new OEditModel(_rxFactory));
290 }
291 
292 //------------------------------------------------------------------------------
293 Sequence<Type> OEditModel::_getTypes()
294 {
295 	return OEditBaseModel::_getTypes();
296 }
297 
298 
299 DBG_NAME(OEditModel);
300 //------------------------------------------------------------------
301 OEditModel::OEditModel(const Reference<XMultiServiceFactory>& _rxFactory)
302     :OEditBaseModel( _rxFactory, FRM_SUN_COMPONENT_RICHTEXTCONTROL, FRM_SUN_CONTROL_TEXTFIELD, sal_True, sal_True )
303     ,m_bMaxTextLenModified(sal_False)
304     ,m_bWritingFormattedFake(sal_False)
305 {
306 	DBG_CTOR(OEditModel,NULL);
307 
308 	m_nClassId = FormComponentType::TEXTFIELD;
309 	initValueProperty( PROPERTY_TEXT, PROPERTY_ID_TEXT );
310 }
311 
312 //------------------------------------------------------------------
313 OEditModel::OEditModel( const OEditModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory )
314     :OEditBaseModel( _pOriginal, _rxFactory )
315     ,m_bMaxTextLenModified(sal_False)
316     ,m_bWritingFormattedFake(sal_False)
317 {
318 	DBG_CTOR( OEditModel, NULL );
319 
320 	// Note that most of the properties are not clone from the original object:
321 	// Things as the format key, it's type, and such, depend on the field being part of a loaded form
322 	// (they're initialized in onConnectedDbColumn). Even if the original object _is_ part of such a form, we ourself
323 	// certainly aren't, so these members are defaulted. If we're inserted into a form which is already loaded,
324 	// they will be set to new values, anyway ....
325 }
326 
327 //------------------------------------------------------------------
328 OEditModel::~OEditModel()
329 {
330 	if (!OComponentHelper::rBHelper.bDisposed)
331 	{
332 		acquire();
333 		dispose();
334 	}
335 
336 	DBG_DTOR(OEditModel,NULL);
337 }
338 
339 //------------------------------------------------------------------------------
340 IMPLEMENT_DEFAULT_CLONING( OEditModel )
341 
342 //------------------------------------------------------------------------------
343 void OEditModel::disposing()
344 {
345 	OEditBaseModel::disposing();
346     m_pValueFormatter.reset();
347 }
348 
349 // XPersistObject
350 //------------------------------------------------------------------------------
351 ::rtl::OUString SAL_CALL OEditModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException)
352 {
353 	return FRM_COMPONENT_EDIT;	// old (non-sun) name for compatibility !
354 }
355 
356 // XServiceInfo
357 //------------------------------------------------------------------------------
358 StringSequence SAL_CALL OEditModel::getSupportedServiceNames() throw()
359 {
360 	StringSequence aSupported = OBoundControlModel::getSupportedServiceNames();
361 
362     sal_Int32 nOldLen = aSupported.getLength();
363 	aSupported.realloc( nOldLen + 8 );
364 	::rtl::OUString* pStoreTo = aSupported.getArray() + nOldLen;
365 
366     *pStoreTo++ = BINDABLE_CONTROL_MODEL;
367     *pStoreTo++ = DATA_AWARE_CONTROL_MODEL;
368     *pStoreTo++ = VALIDATABLE_CONTROL_MODEL;
369 
370     *pStoreTo++ = BINDABLE_DATA_AWARE_CONTROL_MODEL;
371     *pStoreTo++ = VALIDATABLE_BINDABLE_CONTROL_MODEL;
372 
373     *pStoreTo++ = FRM_SUN_COMPONENT_TEXTFIELD;
374     *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_TEXTFIELD;
375     *pStoreTo++ = BINDABLE_DATABASE_TEXT_FIELD;
376 
377 	return aSupported;
378 }
379 
380 // XPropertySet
381 void SAL_CALL OEditModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle ) const
382 {
383 	if ( PROPERTY_ID_PERSISTENCE_MAXTEXTLENGTH == nHandle )
384 	{
385 		if ( m_bMaxTextLenModified )
386 			rValue <<= sal_Int16(0);
387 		else if ( m_xAggregateSet.is() )
388 			rValue = m_xAggregateSet->getPropertyValue(PROPERTY_MAXTEXTLEN);
389 	}
390 	else
391 	{
392 		OEditBaseModel::getFastPropertyValue(rValue, nHandle );
393 	}
394 }
395 
396 //------------------------------------------------------------------------------
397 void OEditModel::describeFixedProperties( Sequence< Property >& _rProps ) const
398 {
399 	BEGIN_DESCRIBE_PROPERTIES( 5, OEditBaseModel )
400 		DECL_PROP2(PERSISTENCE_MAXTEXTLENGTH,sal_Int16,			READONLY, TRANSIENT);
401 		DECL_PROP2(DEFAULT_TEXT,		::rtl::OUString,		BOUND, MAYBEDEFAULT);
402 		DECL_BOOL_PROP1(EMPTY_IS_NULL,							BOUND);
403 		DECL_PROP1(TABINDEX,			sal_Int16,				BOUND);
404 		DECL_BOOL_PROP2(FILTERPROPOSAL,							BOUND, MAYBEDEFAULT);
405 	END_DESCRIBE_PROPERTIES();
406 }
407 
408 //------------------------------------------------------------------------------
409 void OEditModel::describeAggregateProperties( Sequence< Property >& _rAggregateProps ) const
410 {
411     OEditBaseModel::describeAggregateProperties( _rAggregateProps );
412 
413     // our aggregate is a rich text model, which also derives from OControlModel, as
414     // do we, so we need to remove some duplicate properties
415     RemoveProperty( _rAggregateProps, PROPERTY_TABINDEX );
416     RemoveProperty( _rAggregateProps, PROPERTY_CLASSID );
417     RemoveProperty( _rAggregateProps, PROPERTY_NAME );
418     RemoveProperty( _rAggregateProps, PROPERTY_TAG );
419     RemoveProperty( _rAggregateProps, PROPERTY_NATIVE_LOOK );
420 
421 }
422 
423 //------------------------------------------------------------------------------
424 bool OEditModel::implActsAsRichText( ) const
425 {
426     sal_Bool bActAsRichText = sal_False;
427     if ( m_xAggregateSet.is() )
428     {
429         OSL_VERIFY( m_xAggregateSet->getPropertyValue( PROPERTY_RICH_TEXT ) >>= bActAsRichText );
430     }
431     return bActAsRichText;
432 }
433 
434 //------------------------------------------------------------------------------
435 void SAL_CALL OEditModel::reset(  ) throw(RuntimeException)
436 {
437     // no reset if we currently act as rich text control
438     if ( implActsAsRichText() )
439         return;
440 
441     OEditBaseModel::reset();
442 }
443 
444 //------------------------------------------------------------------------------
445 namespace
446 {
447     void lcl_transferProperties( const Reference< XPropertySet >& _rxSource, const Reference< XPropertySet >& _rxDest )
448     {
449         try
450         {
451             Reference< XPropertySetInfo > xSourceInfo;
452             if ( _rxSource.is() )
453                 xSourceInfo = _rxSource->getPropertySetInfo();
454 
455             Reference< XPropertySetInfo > xDestInfo;
456             if ( _rxDest.is() )
457                 xDestInfo = _rxDest->getPropertySetInfo();
458 
459             if ( !xSourceInfo.is() || !xDestInfo.is() )
460             {
461                 OSL_ENSURE( sal_False, "lcl_transferProperties: invalid property set(s)!" );
462                 return;
463             }
464 
465             Sequence< Property > aSourceProps( xSourceInfo->getProperties() );
466             const Property* pSourceProps = aSourceProps.getConstArray();
467             const Property* pSourcePropsEnd = aSourceProps.getConstArray() + aSourceProps.getLength();
468             while ( pSourceProps != pSourcePropsEnd )
469             {
470                 if ( !xDestInfo->hasPropertyByName( pSourceProps->Name ) )
471                 {
472                     ++pSourceProps;
473                     continue;
474                 }
475 
476                 Property aDestProp( xDestInfo->getPropertyByName( pSourceProps->Name ) );
477                 if ( 0 != ( aDestProp.Attributes & PropertyAttribute::READONLY ) )
478                 {
479                     ++pSourceProps;
480                     continue;
481                 }
482 
483                 try
484                 {
485                     _rxDest->setPropertyValue( pSourceProps->Name, _rxSource->getPropertyValue( pSourceProps->Name ) );
486                 }
487                 catch( IllegalArgumentException e )
488                 {
489 #if OSL_DEBUG_LEVEL > 0
490                     ::rtl::OString sMessage( "could not transfer the property named '" );
491                     sMessage += ::rtl::OString( pSourceProps->Name.getStr(), pSourceProps->Name.getLength(), RTL_TEXTENCODING_ASCII_US );
492                     sMessage += ::rtl::OString( "'." );
493                     if ( e.Message.getLength() )
494                     {
495                         sMessage += ::rtl::OString( "\n\nMessage:\n" );
496                         sMessage += ::rtl::OString( e.Message.getStr(), e.Message.getLength(), RTL_TEXTENCODING_ASCII_US );
497                     }
498                     OSL_ENSURE( sal_False, sMessage.getStr() );
499 #endif
500                 }
501 
502                 ++pSourceProps;
503             }
504         }
505         catch( const Exception& )
506         {
507             DBG_UNHANDLED_EXCEPTION();
508         }
509     }
510 }
511 
512 //------------------------------------------------------------------------------
513 void OEditModel::writeAggregate( const Reference< XObjectOutputStream >& _rxOutStream ) const
514 {
515     // we need to fake the writing of our aggregate. Since #i24387#, we have another aggregate,
516     // but for compatibility, we need to use an "old" aggregate for writing and reading
517 
518     Reference< XPropertySet > xFakedAggregate(
519         getContext().createComponent( (rtl::OUString)VCL_CONTROLMODEL_EDIT ),
520         UNO_QUERY
521     );
522     OSL_ENSURE( xFakedAggregate.is(), "OEditModel::writeAggregate: could not create an old EditControlModel!" );
523     if ( !xFakedAggregate.is() )
524         return;
525 
526     lcl_transferProperties( m_xAggregateSet, xFakedAggregate );
527 
528     Reference< XPersistObject > xFakedPersist( xFakedAggregate, UNO_QUERY );
529     OSL_ENSURE( xFakedPersist.is(), "OEditModel::writeAggregate: no XPersistObject!" );
530     if ( xFakedPersist.is() )
531         xFakedPersist->write( _rxOutStream );
532 }
533 
534 //------------------------------------------------------------------------------
535 void OEditModel::readAggregate( const Reference< XObjectInputStream >& _rxInStream )
536 {
537     // we need to fake the reading of our aggregate. Since #i24387#, we have another aggregate,
538     // but for compatibility, we need to use an "old" aggregate for writing and reading
539 
540     Reference< XPropertySet > xFakedAggregate(
541         getContext().createComponent( (rtl::OUString)VCL_CONTROLMODEL_EDIT ),
542         UNO_QUERY
543     );
544     Reference< XPersistObject > xFakedPersist( xFakedAggregate, UNO_QUERY );
545     OSL_ENSURE( xFakedPersist.is(), "OEditModel::readAggregate: no XPersistObject, or no faked aggregate at all!" );
546     if ( xFakedPersist.is() )
547     {
548         xFakedPersist->read( _rxInStream );
549         lcl_transferProperties( xFakedAggregate, m_xAggregateSet );
550     }
551 }
552 
553 //------------------------------------------------------------------------------
554 void OEditModel::write(const Reference<XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
555 {
556 	Any aCurrentText;
557 	sal_Int16 nOldTextLen = 0;
558 	// bin ich gerade loaded und habe dazu zeitweilig die MaxTextLen umgesetzt ?
559 	if ( m_bMaxTextLenModified )
560 	{	// -> fuer die Dauer des Speicherns meinem aggregierten Model die alte TextLen einreden
561 
562 		// before doing this we have to save the current text value of the aggregate, as this may be affected by resetting the text len
563 		// FS - 08.12.99 - 70606
564 		aCurrentText = m_xAggregateSet->getPropertyValue(PROPERTY_TEXT);
565 
566 		m_xAggregateSet->getPropertyValue(PROPERTY_MAXTEXTLEN) >>= nOldTextLen;
567 		m_xAggregateSet->setPropertyValue(PROPERTY_MAXTEXTLEN, makeAny((sal_Int16)0));
568 	}
569 
570 	OEditBaseModel::write(_rxOutStream);
571 
572 	if ( m_bMaxTextLenModified )
573 	{	// wieder zuruecksetzen
574 		m_xAggregateSet->setPropertyValue(PROPERTY_MAXTEXTLEN, makeAny(nOldTextLen));
575 		// and reset the text
576 		// First we set it to an empty string : Without this the second setPropertyValue would not do anything as it thinks
577 		// we aren't changing the prop (it didn't notify the - implicite - change of the text prop while setting the max text len)
578 		// This seems to be a bug with in toolkit's EditControl-implementation.
579 		m_xAggregateSet->setPropertyValue(PROPERTY_TEXT, makeAny(::rtl::OUString()));
580 		m_xAggregateSet->setPropertyValue(PROPERTY_TEXT, aCurrentText);
581 	}
582 }
583 
584 //------------------------------------------------------------------------------
585 void OEditModel::read(const Reference<XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
586 {
587 	OEditBaseModel::read(_rxInStream);
588 
589 	// Some versions (5.1 'til about 552) wrote a wrong DefaultControl-property value which is unknown
590 	// to older versions (5.0).
591 	// correct this ...
592 	if (m_xAggregateSet.is())
593 	{
594 		Any aDefaultControl = m_xAggregateSet->getPropertyValue(PROPERTY_DEFAULTCONTROL);
595 		if	(	(aDefaultControl.getValueType().getTypeClass() == TypeClass_STRING)
596 			&&	(getString(aDefaultControl).compareTo(STARDIV_ONE_FORM_CONTROL_TEXTFIELD) == COMPARE_EQUAL)
597 			)
598 		{
599 			m_xAggregateSet->setPropertyValue( PROPERTY_DEFAULTCONTROL, makeAny( (::rtl::OUString)STARDIV_ONE_FORM_CONTROL_EDIT ) );
600 			// Older as well as current versions should understand this : the former knew only the STARDIV_ONE_FORM_CONTROL_EDIT,
601 			// the latter are registered for both STARDIV_ONE_FORM_CONTROL_EDIT and STARDIV_ONE_FORM_CONTROL_TEXTFIELD.
602 		}
603 	}
604 }
605 
606 //------------------------------------------------------------------------------
607 sal_uInt16 OEditModel::getPersistenceFlags() const
608 {
609 	sal_uInt16 nFlags = OEditBaseModel::getPersistenceFlags();
610 
611 	if (m_bWritingFormattedFake)
612 		nFlags |= PF_FAKE_FORMATTED_FIELD;
613 
614 	return nFlags;
615 }
616 
617 //------------------------------------------------------------------------------
618 void OEditModel::onConnectedDbColumn( const Reference< XInterface >& _rxForm )
619 {
620     Reference< XPropertySet > xField = getField();
621     if ( xField.is() )
622     {
623         m_pValueFormatter.reset( new ::dbtools::FormattedColumnValue( getContext(), Reference< XRowSet >( _rxForm, UNO_QUERY ), xField ) );
624 
625         if ( m_pValueFormatter->getKeyType() != NumberFormat::SCIENTIFIC )
626 		{
627 			m_bMaxTextLenModified =	getINT16(m_xAggregateSet->getPropertyValue(PROPERTY_MAXTEXTLEN)) != 0;
628 			if ( !m_bMaxTextLenModified )
629 			{
630 				sal_Int32 nFieldLen = 0;
631 				xField->getPropertyValue(::rtl::OUString::createFromAscii("Precision")) >>= nFieldLen;
632 
633 				if (nFieldLen && nFieldLen <= USHRT_MAX)
634 				{
635 					Any aVal;
636 					aVal <<= (sal_Int16)nFieldLen;
637 					m_xAggregateSet->setPropertyValue(PROPERTY_MAXTEXTLEN, aVal);
638 
639 					m_bMaxTextLenModified = sal_True;
640 				}
641 			}
642 			else
643 				m_bMaxTextLenModified = sal_False; // to get sure that the text len won't be set in unloaded
644 		}
645 	}
646 }
647 
648 //------------------------------------------------------------------------------
649 void OEditModel::onDisconnectedDbColumn()
650 {
651 	OEditBaseModel::onDisconnectedDbColumn();
652 
653     m_pValueFormatter.reset();
654 
655     if ( hasField() && m_bMaxTextLenModified )
656 	{
657 		Any aVal;
658 		aVal <<= (sal_Int16)0;	// nur wenn es 0 war, habe ich es in onConnectedDbColumn umgesetzt
659 		m_xAggregateSet->setPropertyValue(PROPERTY_MAXTEXTLEN, aVal);
660 		m_bMaxTextLenModified = sal_False;
661 	}
662 }
663 
664 //------------------------------------------------------------------------------
665 sal_Bool OEditModel::approveDbColumnType( sal_Int32 _nColumnType )
666 {
667     // if we act as rich text curently, we do not allow binding to a database column
668     if ( implActsAsRichText() )
669         return sal_False;
670 
671     return OEditBaseModel::approveDbColumnType( _nColumnType );
672 }
673 
674 //------------------------------------------------------------------------------
675 void OEditModel::resetNoBroadcast()
676 {
677     OEditBaseModel::resetNoBroadcast();
678 }
679 
680 //------------------------------------------------------------------------------
681 sal_Bool OEditModel::commitControlValueToDbColumn( bool /*_bPostReset*/ )
682 {
683     Any aNewValue( m_xAggregateFastSet->getFastPropertyValue( getValuePropertyAggHandle() ) );
684 
685     ::rtl::OUString sNewValue;
686     aNewValue >>= sNewValue;
687 
688 	if  (   !aNewValue.hasValue()
689         ||  (   !sNewValue.getLength()      // an empty string
690             &&  m_bEmptyIsNull              // which should be interpreted as NULL
691             )
692         )
693     {
694 		m_xColumnUpdate->updateNull();
695     }
696 	else
697 	{
698         OSL_PRECOND( m_pValueFormatter.get(), "OEditModel::commitControlValueToDbColumn: no value formatter!" );
699 		try
700 		{
701             if ( m_pValueFormatter.get() )
702             {
703                 if ( !m_pValueFormatter->setFormattedValue( sNewValue ) )
704                     return sal_False;
705             }
706 			else
707 				m_xColumnUpdate->updateString( sNewValue );
708 		}
709 		catch ( const Exception& )
710 		{
711 			return sal_False;
712 		}
713 	}
714 
715     return sal_True;
716 }
717 
718 //------------------------------------------------------------------------------
719 Any OEditModel::translateDbColumnToControlValue()
720 {
721     OSL_PRECOND( m_pValueFormatter.get(), "OEditModel::translateDbColumnToControlValue: no value formatter!" );
722     Any aRet;
723     if ( m_pValueFormatter.get() )
724     {
725         ::rtl::OUString sValue( m_pValueFormatter->getFormattedValue() );
726         if  (   !sValue.getLength()
727             &&  m_pValueFormatter->getColumn().is()
728             &&  m_pValueFormatter->getColumn()->wasNull()
729             )
730         {
731         }
732         else
733         {
734 	        // #i2817# OJ
735 	        sal_uInt16 nMaxTextLen = getINT16( m_xAggregateSet->getPropertyValue( PROPERTY_MAXTEXTLEN ) );
736 	        if ( nMaxTextLen && sValue.getLength() > nMaxTextLen )
737 	        {
738 		        sal_Int32 nDiff = sValue.getLength() - nMaxTextLen;
739 		        sValue = sValue.replaceAt( nMaxTextLen, nDiff, ::rtl::OUString() );
740 	        }
741 
742 	        aRet <<= sValue;
743         }
744     }
745 
746     return aRet.hasValue() ? aRet : makeAny( ::rtl::OUString() );
747 }
748 
749 //------------------------------------------------------------------------------
750 Any OEditModel::getDefaultForReset() const
751 {
752     return makeAny( m_aDefaultText );
753 }
754 
755 //.........................................................................
756 }
757 //.........................................................................
758 
759