1*24acc546SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*24acc546SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*24acc546SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*24acc546SAndrew Rist  * distributed with this work for additional information
6*24acc546SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*24acc546SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*24acc546SAndrew Rist  * "License"); you may not use this file except in compliance
9*24acc546SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*24acc546SAndrew Rist  *
11*24acc546SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*24acc546SAndrew Rist  *
13*24acc546SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*24acc546SAndrew Rist  * software distributed under the License is distributed on an
15*24acc546SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*24acc546SAndrew Rist  * KIND, either express or implied.  See the License for the
17*24acc546SAndrew Rist  * specific language governing permissions and limitations
18*24acc546SAndrew Rist  * under the License.
19*24acc546SAndrew Rist  *
20*24acc546SAndrew Rist  *************************************************************/
21*24acc546SAndrew Rist 
22*24acc546SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_forms.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include "componenttools.hxx"
28cdf0e10cSrcweir #include "FormComponent.hxx"
29cdf0e10cSrcweir #include "frm_resource.hrc"
30cdf0e10cSrcweir #include "frm_resource.hxx"
31cdf0e10cSrcweir #include "property.hrc"
32cdf0e10cSrcweir #include "services.hxx"
33cdf0e10cSrcweir 
34cdf0e10cSrcweir /** === begin UNO includes === **/
35cdf0e10cSrcweir #include <com/sun/star/awt/XTextComponent.hpp>
36cdf0e10cSrcweir #include <com/sun/star/awt/XVclWindowPeer.hpp>
37cdf0e10cSrcweir #include <com/sun/star/awt/XWindow.hpp>
38cdf0e10cSrcweir #include <com/sun/star/form/XForm.hpp>
39cdf0e10cSrcweir #include <com/sun/star/form/XLoadable.hpp>
40cdf0e10cSrcweir #include <com/sun/star/io/XMarkableStream.hpp>
41cdf0e10cSrcweir #include <com/sun/star/lang/DisposedException.hpp>
42cdf0e10cSrcweir #include <com/sun/star/sdb/XRowSetChangeBroadcaster.hpp>
43cdf0e10cSrcweir #include <com/sun/star/sdb/XRowSetSupplier.hpp>
44cdf0e10cSrcweir #include <com/sun/star/sdbc/ColumnValue.hpp>
45cdf0e10cSrcweir #include <com/sun/star/sdbc/DataType.hpp>
46cdf0e10cSrcweir #include <com/sun/star/util/XModifyBroadcaster.hpp>
47cdf0e10cSrcweir /** === end UNO includes === **/
48cdf0e10cSrcweir 
49cdf0e10cSrcweir #include <comphelper/basicio.hxx>
50cdf0e10cSrcweir #include <comphelper/guarding.hxx>
51cdf0e10cSrcweir #include <comphelper/listenernotification.hxx>
52cdf0e10cSrcweir #include <comphelper/property.hxx>
53cdf0e10cSrcweir #include <connectivity/dbtools.hxx>
54cdf0e10cSrcweir #include <cppuhelper/queryinterface.hxx>
55cdf0e10cSrcweir #include <rtl/logfile.hxx>
56cdf0e10cSrcweir #include <toolkit/helper/emptyfontdescriptor.hxx>
57cdf0e10cSrcweir #include <tools/debug.hxx>
58cdf0e10cSrcweir #include <tools/diagnose_ex.h>
59cdf0e10cSrcweir 
60cdf0e10cSrcweir #include <functional>
61cdf0e10cSrcweir #include <algorithm>
62cdf0e10cSrcweir 
63cdf0e10cSrcweir #include <functional>
64cdf0e10cSrcweir #include <algorithm>
65cdf0e10cSrcweir 
66cdf0e10cSrcweir 
67cdf0e10cSrcweir //... namespace frm .......................................................
68cdf0e10cSrcweir namespace frm
69cdf0e10cSrcweir {
70cdf0e10cSrcweir //.........................................................................
71cdf0e10cSrcweir 
72cdf0e10cSrcweir     using namespace ::com::sun::star::uno;
73cdf0e10cSrcweir     using namespace ::com::sun::star::sdb;
74cdf0e10cSrcweir     using namespace ::com::sun::star::sdbc;
75cdf0e10cSrcweir     using namespace ::com::sun::star::sdbcx;
76cdf0e10cSrcweir     using namespace ::com::sun::star::beans;
77cdf0e10cSrcweir     using namespace ::com::sun::star::container;
78cdf0e10cSrcweir     using namespace ::com::sun::star::form;
79cdf0e10cSrcweir     using namespace ::com::sun::star::awt;
80cdf0e10cSrcweir     using namespace ::com::sun::star::io;
81cdf0e10cSrcweir     using namespace ::com::sun::star::lang;
82cdf0e10cSrcweir     using namespace ::com::sun::star::util;
83cdf0e10cSrcweir     using namespace ::com::sun::star::form::binding;
84cdf0e10cSrcweir     using namespace ::com::sun::star::form::validation;
85cdf0e10cSrcweir     using namespace ::dbtools;
86cdf0e10cSrcweir     using namespace ::comphelper;
87cdf0e10cSrcweir 
88cdf0e10cSrcweir     //=========================================================================
89cdf0e10cSrcweir     //= FieldChangeNotifier
90cdf0e10cSrcweir     //=========================================================================
91cdf0e10cSrcweir     //-------------------------------------------------------------------------
92cdf0e10cSrcweir     void ControlModelLock::impl_notifyAll_nothrow()
93cdf0e10cSrcweir     {
94cdf0e10cSrcweir         m_rModel.firePropertyChanges( m_aHandles, m_aOldValues, m_aNewValues, OControlModel::LockAccess() );
95cdf0e10cSrcweir     }
96cdf0e10cSrcweir 
97cdf0e10cSrcweir     //-------------------------------------------------------------------------
98cdf0e10cSrcweir     void ControlModelLock::addPropertyNotification( const sal_Int32 _nHandle, const Any& _rOldValue, const Any& _rNewValue )
99cdf0e10cSrcweir     {
100cdf0e10cSrcweir         sal_Int32 nOldLength = m_aHandles.getLength();
101cdf0e10cSrcweir         if  (   ( nOldLength != m_aOldValues.getLength() )
102cdf0e10cSrcweir             ||  ( nOldLength != m_aNewValues.getLength() )
103cdf0e10cSrcweir             )
104cdf0e10cSrcweir             throw RuntimeException( ::rtl::OUString(), m_rModel );
105cdf0e10cSrcweir 
106cdf0e10cSrcweir         m_aHandles.realloc( nOldLength + 1 );
107cdf0e10cSrcweir         m_aHandles[ nOldLength ] = _nHandle;
108cdf0e10cSrcweir         m_aOldValues.realloc( nOldLength + 1 );
109cdf0e10cSrcweir         m_aOldValues[ nOldLength ] = _rOldValue;
110cdf0e10cSrcweir         m_aNewValues.realloc( nOldLength + 1 );
111cdf0e10cSrcweir         m_aNewValues[ nOldLength ] = _rNewValue;
112cdf0e10cSrcweir     }
113cdf0e10cSrcweir 
114cdf0e10cSrcweir     //=========================================================================
115cdf0e10cSrcweir     //= FieldChangeNotifier
116cdf0e10cSrcweir     //=========================================================================
117cdf0e10cSrcweir     //-------------------------------------------------------------------------
118cdf0e10cSrcweir     class FieldChangeNotifier
119cdf0e10cSrcweir     {
120cdf0e10cSrcweir     public:
121cdf0e10cSrcweir         FieldChangeNotifier( ControlModelLock& _rLock )
122cdf0e10cSrcweir             :m_rLock( _rLock )
123cdf0e10cSrcweir             ,m_rModel( dynamic_cast< OBoundControlModel& >( _rLock.getModel() ) )
124cdf0e10cSrcweir         {
125cdf0e10cSrcweir             m_xOldField = m_rModel.getField();
126cdf0e10cSrcweir         }
127cdf0e10cSrcweir 
128cdf0e10cSrcweir         ~FieldChangeNotifier()
129cdf0e10cSrcweir         {
130cdf0e10cSrcweir             Reference< XPropertySet > xNewField( m_rModel.getField() );
131cdf0e10cSrcweir             if ( m_xOldField != xNewField )
132cdf0e10cSrcweir                 m_rLock.addPropertyNotification( PROPERTY_ID_BOUNDFIELD, makeAny( m_xOldField ), makeAny( xNewField ) );
133cdf0e10cSrcweir         }
134cdf0e10cSrcweir 
135cdf0e10cSrcweir     private:
136cdf0e10cSrcweir         ControlModelLock&           m_rLock;
137cdf0e10cSrcweir         OBoundControlModel&         m_rModel;
138cdf0e10cSrcweir         Reference< XPropertySet >   m_xOldField;
139cdf0e10cSrcweir     };
140cdf0e10cSrcweir 
141cdf0e10cSrcweir //=============================================================================
142cdf0e10cSrcweir //= base class for form layer controls
143cdf0e10cSrcweir //=============================================================================
144cdf0e10cSrcweir DBG_NAME(frm_OControl)
145cdf0e10cSrcweir //------------------------------------------------------------------------------
146cdf0e10cSrcweir OControl::OControl( const Reference< XMultiServiceFactory >& _rxFactory, const rtl::OUString& _rAggregateService, const sal_Bool _bSetDelegator )
147cdf0e10cSrcweir 			:OComponentHelper(m_aMutex)
148cdf0e10cSrcweir             ,m_aContext( _rxFactory )
149cdf0e10cSrcweir {
150cdf0e10cSrcweir 	DBG_CTOR(frm_OControl, NULL);
151cdf0e10cSrcweir 	// VCL-Control aggregieren
152cdf0e10cSrcweir 	// bei Aggregation den Refcount um eins erhoehen da im setDelegator
153cdf0e10cSrcweir 	// das Aggregat selbst den Refcount erhoeht
154cdf0e10cSrcweir 	increment( m_refCount );
155cdf0e10cSrcweir 	{
156cdf0e10cSrcweir 		m_xAggregate = m_xAggregate.query( _rxFactory->createInstance( _rAggregateService ) );
157cdf0e10cSrcweir 		m_xControl = m_xControl.query( m_xAggregate );
158cdf0e10cSrcweir 	}
159cdf0e10cSrcweir 	decrement( m_refCount );
160cdf0e10cSrcweir 
161cdf0e10cSrcweir     if ( _bSetDelegator )
162cdf0e10cSrcweir         doSetDelegator();
163cdf0e10cSrcweir }
164cdf0e10cSrcweir 
165cdf0e10cSrcweir //------------------------------------------------------------------------------
166cdf0e10cSrcweir OControl::~OControl()
167cdf0e10cSrcweir {
168cdf0e10cSrcweir 	DBG_DTOR(frm_OControl, NULL);
169cdf0e10cSrcweir     doResetDelegator();
170cdf0e10cSrcweir }
171cdf0e10cSrcweir 
172cdf0e10cSrcweir //------------------------------------------------------------------------------
173cdf0e10cSrcweir void OControl::doResetDelegator()
174cdf0e10cSrcweir {
175cdf0e10cSrcweir 	if ( m_xAggregate.is() )
176cdf0e10cSrcweir 		m_xAggregate->setDelegator( NULL );
177cdf0e10cSrcweir }
178cdf0e10cSrcweir 
179cdf0e10cSrcweir //------------------------------------------------------------------------------
180cdf0e10cSrcweir void OControl::doSetDelegator()
181cdf0e10cSrcweir {
182cdf0e10cSrcweir 	increment( m_refCount );
183cdf0e10cSrcweir 	if ( m_xAggregate.is() )
184cdf0e10cSrcweir 	{   // those brackets are important for some compilers, don't remove!
185cdf0e10cSrcweir         // (they ensure that the temporary object created in the line below
186cdf0e10cSrcweir         // is destroyed *before* the refcount-decrement)
187cdf0e10cSrcweir 		m_xAggregate->setDelegator( static_cast< XWeak* >( this ) );
188cdf0e10cSrcweir 	}
189cdf0e10cSrcweir 	decrement( m_refCount );
190cdf0e10cSrcweir }
191cdf0e10cSrcweir 
192cdf0e10cSrcweir // UNO Anbindung
193cdf0e10cSrcweir //------------------------------------------------------------------------------
194cdf0e10cSrcweir Any SAL_CALL OControl::queryAggregation( const Type& _rType ) throw(RuntimeException)
195cdf0e10cSrcweir {
196cdf0e10cSrcweir 	// ask the base class
197cdf0e10cSrcweir 	Any aReturn( OComponentHelper::queryAggregation(_rType) );
198cdf0e10cSrcweir 	// ask our own interfaces
199cdf0e10cSrcweir 	if (!aReturn.hasValue())
200cdf0e10cSrcweir 	{
201cdf0e10cSrcweir 		aReturn = OControl_BASE::queryInterface(_rType);
202cdf0e10cSrcweir 		// ask our aggregate
203cdf0e10cSrcweir 		if (!aReturn.hasValue() && m_xAggregate.is())
204cdf0e10cSrcweir 			aReturn = m_xAggregate->queryAggregation(_rType);
205cdf0e10cSrcweir 	}
206cdf0e10cSrcweir 
207cdf0e10cSrcweir 	return aReturn;
208cdf0e10cSrcweir }
209cdf0e10cSrcweir 
210cdf0e10cSrcweir //------------------------------------------------------------------------------
211cdf0e10cSrcweir Sequence<sal_Int8> SAL_CALL OControl::getImplementationId() throw(RuntimeException)
212cdf0e10cSrcweir {
213cdf0e10cSrcweir 	return OImplementationIds::getImplementationId(getTypes());
214cdf0e10cSrcweir }
215cdf0e10cSrcweir 
216cdf0e10cSrcweir //------------------------------------------------------------------------------
217cdf0e10cSrcweir Sequence<Type> SAL_CALL OControl::getTypes() throw(RuntimeException)
218cdf0e10cSrcweir {
219cdf0e10cSrcweir     TypeBag aTypes( _getTypes() );
220cdf0e10cSrcweir 
221cdf0e10cSrcweir     Reference< XTypeProvider > xProv;
222cdf0e10cSrcweir 	if ( query_aggregation( m_xAggregate, xProv ) )
223cdf0e10cSrcweir         aTypes.addTypes( xProv->getTypes() );
224cdf0e10cSrcweir 
225cdf0e10cSrcweir     return aTypes.getTypes();
226cdf0e10cSrcweir }
227cdf0e10cSrcweir 
228cdf0e10cSrcweir //------------------------------------------------------------------------------
229cdf0e10cSrcweir Sequence<Type> OControl::_getTypes()
230cdf0e10cSrcweir {
231cdf0e10cSrcweir     return TypeBag( OComponentHelper::getTypes(), OControl_BASE::getTypes() ).getTypes();
232cdf0e10cSrcweir }
233cdf0e10cSrcweir 
234cdf0e10cSrcweir //------------------------------------------------------------------------------
235cdf0e10cSrcweir void OControl::initFormControlPeer( const Reference< XWindowPeer >& /*_rxPeer*/ )
236cdf0e10cSrcweir {
237cdf0e10cSrcweir     // nothing to do here
238cdf0e10cSrcweir }
239cdf0e10cSrcweir 
240cdf0e10cSrcweir // OComponentHelper
241cdf0e10cSrcweir //------------------------------------------------------------------------------
242cdf0e10cSrcweir void OControl::disposing()
243cdf0e10cSrcweir {
244cdf0e10cSrcweir 	OComponentHelper::disposing();
245cdf0e10cSrcweir 
246cdf0e10cSrcweir     m_aWindowStateGuard.attach( NULL, NULL );
247cdf0e10cSrcweir 
248cdf0e10cSrcweir     Reference< XComponent > xComp;
249cdf0e10cSrcweir 	if (query_aggregation(m_xAggregate, xComp))
250cdf0e10cSrcweir 		xComp->dispose();
251cdf0e10cSrcweir }
252cdf0e10cSrcweir 
253cdf0e10cSrcweir // XServiceInfo
254cdf0e10cSrcweir //------------------------------------------------------------------------------
255cdf0e10cSrcweir sal_Bool SAL_CALL OControl::supportsService(const rtl::OUString& _rsServiceName) throw ( RuntimeException)
256cdf0e10cSrcweir {
257cdf0e10cSrcweir     Sequence<rtl::OUString> aSupported = getSupportedServiceNames();
258cdf0e10cSrcweir 	const rtl::OUString* pSupported = aSupported.getConstArray();
259cdf0e10cSrcweir 	for (sal_Int32 i=0; i<aSupported.getLength(); ++i, ++pSupported)
260cdf0e10cSrcweir 		if (pSupported->equals(_rsServiceName))
261cdf0e10cSrcweir 			return sal_True;
262cdf0e10cSrcweir 	return sal_False;
263cdf0e10cSrcweir }
264cdf0e10cSrcweir 
265cdf0e10cSrcweir //------------------------------------------------------------------------------
266cdf0e10cSrcweir Sequence< ::rtl::OUString > OControl::getAggregateServiceNames()
267cdf0e10cSrcweir {
268cdf0e10cSrcweir     Sequence< ::rtl::OUString > aAggServices;
269cdf0e10cSrcweir     Reference< XServiceInfo > xInfo;
270cdf0e10cSrcweir 	if ( query_aggregation( m_xAggregate, xInfo ) )
271cdf0e10cSrcweir 		aAggServices = xInfo->getSupportedServiceNames();
272cdf0e10cSrcweir     return aAggServices;
273cdf0e10cSrcweir }
274cdf0e10cSrcweir 
275cdf0e10cSrcweir //------------------------------------------------------------------------------
276cdf0e10cSrcweir Sequence<rtl::OUString> SAL_CALL OControl::getSupportedServiceNames() throw(RuntimeException)
277cdf0e10cSrcweir {
278cdf0e10cSrcweir     return ::comphelper::concatSequences(
279cdf0e10cSrcweir         getAggregateServiceNames(),
280cdf0e10cSrcweir         getSupportedServiceNames_Static()
281cdf0e10cSrcweir    );
282cdf0e10cSrcweir }
283cdf0e10cSrcweir 
284cdf0e10cSrcweir //------------------------------------------------------------------------------
285cdf0e10cSrcweir Sequence< ::rtl::OUString > SAL_CALL OControl::getSupportedServiceNames_Static() throw( RuntimeException )
286cdf0e10cSrcweir {
287cdf0e10cSrcweir     // no own supported service names
288cdf0e10cSrcweir     return Sequence< ::rtl::OUString >();
289cdf0e10cSrcweir }
290cdf0e10cSrcweir 
291cdf0e10cSrcweir // XEventListener
292cdf0e10cSrcweir //------------------------------------------------------------------------------
293cdf0e10cSrcweir void SAL_CALL OControl::disposing(const com::sun::star::lang::EventObject& _rEvent) throw (RuntimeException)
294cdf0e10cSrcweir {
295cdf0e10cSrcweir 	Reference< XInterface > xAggAsIface;
296cdf0e10cSrcweir 	query_aggregation(m_xAggregate, xAggAsIface);
297cdf0e10cSrcweir 
298cdf0e10cSrcweir 	// does the disposing come from the aggregate ?
299cdf0e10cSrcweir     if (xAggAsIface != Reference< XInterface >(_rEvent.Source, UNO_QUERY))
300cdf0e10cSrcweir 	{	// no -> forward it
301cdf0e10cSrcweir                 Reference<com::sun::star::lang::XEventListener> xListener;
302cdf0e10cSrcweir 		if (query_aggregation(m_xAggregate, xListener))
303cdf0e10cSrcweir 			xListener->disposing(_rEvent);
304cdf0e10cSrcweir 	}
305cdf0e10cSrcweir }
306cdf0e10cSrcweir 
307cdf0e10cSrcweir // XControl
308cdf0e10cSrcweir //------------------------------------------------------------------------------
309cdf0e10cSrcweir void SAL_CALL OControl::setContext(const Reference< XInterface >& Context) throw (RuntimeException)
310cdf0e10cSrcweir {
311cdf0e10cSrcweir 	if (m_xControl.is())
312cdf0e10cSrcweir 		m_xControl->setContext(Context);
313cdf0e10cSrcweir }
314cdf0e10cSrcweir 
315cdf0e10cSrcweir //------------------------------------------------------------------------------
316cdf0e10cSrcweir Reference< XInterface > SAL_CALL OControl::getContext() throw (RuntimeException)
317cdf0e10cSrcweir {
318cdf0e10cSrcweir 	return m_xControl.is() ? m_xControl->getContext() : Reference< XInterface >();
319cdf0e10cSrcweir }
320cdf0e10cSrcweir 
321cdf0e10cSrcweir //------------------------------------------------------------------------------
322cdf0e10cSrcweir void OControl::impl_resetStateGuard_nothrow()
323cdf0e10cSrcweir {
324cdf0e10cSrcweir     Reference< XWindow2 > xWindow;
325cdf0e10cSrcweir     Reference< XControlModel > xModel;
326cdf0e10cSrcweir     try
327cdf0e10cSrcweir     {
328cdf0e10cSrcweir         xWindow.set( getPeer(), UNO_QUERY );
329cdf0e10cSrcweir         xModel.set( getModel(), UNO_QUERY );
330cdf0e10cSrcweir     }
331cdf0e10cSrcweir     catch( const Exception& )
332cdf0e10cSrcweir     {
333cdf0e10cSrcweir     	DBG_UNHANDLED_EXCEPTION();
334cdf0e10cSrcweir     }
335cdf0e10cSrcweir     m_aWindowStateGuard.attach( xWindow, xModel );
336cdf0e10cSrcweir }
337cdf0e10cSrcweir 
338cdf0e10cSrcweir //------------------------------------------------------------------------------
339cdf0e10cSrcweir void SAL_CALL OControl::createPeer(const Reference<XToolkit>& _rxToolkit, const Reference<XWindowPeer>& _rxParent) throw (RuntimeException)
340cdf0e10cSrcweir {
341cdf0e10cSrcweir 	if ( m_xControl.is() )
342cdf0e10cSrcweir     {
343cdf0e10cSrcweir 		m_xControl->createPeer( _rxToolkit, _rxParent );
344cdf0e10cSrcweir 
345cdf0e10cSrcweir         initFormControlPeer( getPeer() );
346cdf0e10cSrcweir 
347cdf0e10cSrcweir         impl_resetStateGuard_nothrow();
348cdf0e10cSrcweir     }
349cdf0e10cSrcweir }
350cdf0e10cSrcweir 
351cdf0e10cSrcweir //------------------------------------------------------------------------------
352cdf0e10cSrcweir Reference<XWindowPeer> SAL_CALL OControl::getPeer() throw ( RuntimeException)
353cdf0e10cSrcweir {
354cdf0e10cSrcweir     return m_xControl.is() ? m_xControl->getPeer() : Reference<XWindowPeer>();
355cdf0e10cSrcweir }
356cdf0e10cSrcweir 
357cdf0e10cSrcweir //------------------------------------------------------------------------------
358cdf0e10cSrcweir sal_Bool SAL_CALL OControl::setModel(const Reference<XControlModel>& Model) throw ( RuntimeException)
359cdf0e10cSrcweir {
360cdf0e10cSrcweir     if ( !m_xControl.is() )
361cdf0e10cSrcweir         return sal_False;
362cdf0e10cSrcweir 
363cdf0e10cSrcweir     sal_Bool bSuccess = m_xControl->setModel( Model );
364cdf0e10cSrcweir     impl_resetStateGuard_nothrow();
365cdf0e10cSrcweir 	return bSuccess;
366cdf0e10cSrcweir }
367cdf0e10cSrcweir 
368cdf0e10cSrcweir //------------------------------------------------------------------------------
369cdf0e10cSrcweir Reference<XControlModel> SAL_CALL OControl::getModel() throw ( RuntimeException)
370cdf0e10cSrcweir {
371cdf0e10cSrcweir     return m_xControl.is() ? m_xControl->getModel() : Reference<XControlModel>();
372cdf0e10cSrcweir }
373cdf0e10cSrcweir 
374cdf0e10cSrcweir //------------------------------------------------------------------------------
375cdf0e10cSrcweir Reference<XView> SAL_CALL OControl::getView() throw ( RuntimeException)
376cdf0e10cSrcweir {
377cdf0e10cSrcweir     return m_xControl.is() ? m_xControl->getView() : Reference<XView>();
378cdf0e10cSrcweir }
379cdf0e10cSrcweir 
380cdf0e10cSrcweir //------------------------------------------------------------------------------
381cdf0e10cSrcweir void SAL_CALL OControl::setDesignMode(sal_Bool bOn) throw ( RuntimeException)
382cdf0e10cSrcweir {
383cdf0e10cSrcweir 	if (m_xControl.is())
384cdf0e10cSrcweir 		m_xControl->setDesignMode(bOn);
385cdf0e10cSrcweir }
386cdf0e10cSrcweir 
387cdf0e10cSrcweir //------------------------------------------------------------------------------
388cdf0e10cSrcweir sal_Bool SAL_CALL OControl::isDesignMode() throw ( RuntimeException)
389cdf0e10cSrcweir {
390cdf0e10cSrcweir 	return m_xControl.is() ? m_xControl->isDesignMode() : sal_True;
391cdf0e10cSrcweir }
392cdf0e10cSrcweir 
393cdf0e10cSrcweir //------------------------------------------------------------------------------
394cdf0e10cSrcweir sal_Bool SAL_CALL OControl::isTransparent() throw ( RuntimeException)
395cdf0e10cSrcweir {
396cdf0e10cSrcweir 	return m_xControl.is() ? m_xControl->isTransparent() : sal_True;
397cdf0e10cSrcweir }
398cdf0e10cSrcweir 
399cdf0e10cSrcweir //==================================================================
400cdf0e10cSrcweir //= OBoundControl
401cdf0e10cSrcweir //==================================================================
402cdf0e10cSrcweir DBG_NAME(frm_OBoundControl);
403cdf0e10cSrcweir //------------------------------------------------------------------
404cdf0e10cSrcweir OBoundControl::OBoundControl( const Reference< XMultiServiceFactory >& _rxFactory,
405cdf0e10cSrcweir             const ::rtl::OUString& _rAggregateService, const sal_Bool _bSetDelegator )
406cdf0e10cSrcweir     :OControl( _rxFactory, _rAggregateService, _bSetDelegator )
407cdf0e10cSrcweir     ,m_bLocked(sal_False)
408cdf0e10cSrcweir     ,m_aOriginalFont( EmptyFontDescriptor() )
409cdf0e10cSrcweir     ,m_nOriginalTextLineColor( 0 )
410cdf0e10cSrcweir {
411cdf0e10cSrcweir 	DBG_CTOR(frm_OBoundControl, NULL);
412cdf0e10cSrcweir }
413cdf0e10cSrcweir 
414cdf0e10cSrcweir //------------------------------------------------------------------
415cdf0e10cSrcweir OBoundControl::~OBoundControl()
416cdf0e10cSrcweir {
417cdf0e10cSrcweir 	DBG_DTOR(frm_OBoundControl, NULL);
418cdf0e10cSrcweir }
419cdf0e10cSrcweir // -----------------------------------------------------------------------------
420cdf0e10cSrcweir Sequence< Type>	OBoundControl::_getTypes()
421cdf0e10cSrcweir {
422cdf0e10cSrcweir     return TypeBag( OControl::_getTypes(), OBoundControl_BASE::getTypes() ).getTypes();
423cdf0e10cSrcweir }
424cdf0e10cSrcweir //------------------------------------------------------------------
425cdf0e10cSrcweir Any SAL_CALL OBoundControl::queryAggregation(const Type& _rType) throw(RuntimeException)
426cdf0e10cSrcweir {
427cdf0e10cSrcweir     Any aReturn;
428cdf0e10cSrcweir 
429cdf0e10cSrcweir     // XTypeProvider first - don't ask the OBoundControl_BASE, it would deliver incomplete types
430cdf0e10cSrcweir     if ( _rType.equals( ::getCppuType( static_cast< Reference< XTypeProvider >* >( NULL ) ) ) )
431cdf0e10cSrcweir         aReturn = OControl::queryAggregation( _rType );
432cdf0e10cSrcweir 
433cdf0e10cSrcweir 	// ask our own interfaces
434cdf0e10cSrcweir     // (do this first (except XTypeProvider ) - we want to "overwrite" XPropertiesChangeListener)
435cdf0e10cSrcweir     if ( !aReturn.hasValue() )
436cdf0e10cSrcweir 	    aReturn = OBoundControl_BASE::queryInterface( _rType );
437cdf0e10cSrcweir 
438cdf0e10cSrcweir     // ask the base class
439cdf0e10cSrcweir 	if ( !aReturn.hasValue() )
440cdf0e10cSrcweir     	aReturn = OControl::queryAggregation( _rType );
441cdf0e10cSrcweir 
442cdf0e10cSrcweir 	return aReturn;
443cdf0e10cSrcweir }
444cdf0e10cSrcweir 
445cdf0e10cSrcweir //------------------------------------------------------------------
446cdf0e10cSrcweir sal_Bool SAL_CALL OBoundControl::getLock() throw(RuntimeException)
447cdf0e10cSrcweir {
448cdf0e10cSrcweir 	return m_bLocked;
449cdf0e10cSrcweir }
450cdf0e10cSrcweir 
451cdf0e10cSrcweir //------------------------------------------------------------------
452cdf0e10cSrcweir void SAL_CALL OBoundControl::setLock(sal_Bool _bLock) throw(RuntimeException)
453cdf0e10cSrcweir {
454cdf0e10cSrcweir 	if (m_bLocked == _bLock)
455cdf0e10cSrcweir 		return;
456cdf0e10cSrcweir 
457cdf0e10cSrcweir 	osl::MutexGuard aGuard(m_aMutex);
458cdf0e10cSrcweir 	_setLock(_bLock);
459cdf0e10cSrcweir 	m_bLocked = _bLock;
460cdf0e10cSrcweir }
461cdf0e10cSrcweir 
462cdf0e10cSrcweir //------------------------------------------------------------------
463cdf0e10cSrcweir void OBoundControl::_setLock(sal_Bool _bLock)
464cdf0e10cSrcweir {
465cdf0e10cSrcweir 	// try to set the text component to readonly
466cdf0e10cSrcweir     Reference< XWindowPeer > xPeer = getPeer();
467cdf0e10cSrcweir     Reference< XTextComponent > xText( xPeer, UNO_QUERY );
468cdf0e10cSrcweir 
469cdf0e10cSrcweir 	if ( xText.is() )
470cdf0e10cSrcweir 		xText->setEditable( !_bLock );
471cdf0e10cSrcweir 	else
472cdf0e10cSrcweir 	{
473cdf0e10cSrcweir 		// disable the window
474cdf0e10cSrcweir         Reference< XWindow > xComp( xPeer, UNO_QUERY );
475cdf0e10cSrcweir 		if ( xComp.is() )
476cdf0e10cSrcweir 			xComp->setEnable( !_bLock );
477cdf0e10cSrcweir 	}
478cdf0e10cSrcweir }
479cdf0e10cSrcweir 
480cdf0e10cSrcweir //--------------------------------------------------------------------
481cdf0e10cSrcweir sal_Bool SAL_CALL OBoundControl::setModel( const Reference< XControlModel >& _rxModel ) throw (RuntimeException)
482cdf0e10cSrcweir {
483cdf0e10cSrcweir     return OControl::setModel( _rxModel );
484cdf0e10cSrcweir }
485cdf0e10cSrcweir 
486cdf0e10cSrcweir //--------------------------------------------------------------------
487cdf0e10cSrcweir void SAL_CALL OBoundControl::disposing(const EventObject& Source) throw (RuntimeException)
488cdf0e10cSrcweir {
489cdf0e10cSrcweir     // just disambiguate
490cdf0e10cSrcweir     OControl::disposing(Source);
491cdf0e10cSrcweir }
492cdf0e10cSrcweir 
493cdf0e10cSrcweir //--------------------------------------------------------------------
494cdf0e10cSrcweir void OBoundControl::disposing()
495cdf0e10cSrcweir {
496cdf0e10cSrcweir     OControl::disposing();
497cdf0e10cSrcweir }
498cdf0e10cSrcweir 
499cdf0e10cSrcweir //==================================================================
500cdf0e10cSrcweir //= OControlModel
501cdf0e10cSrcweir //==================================================================
502cdf0e10cSrcweir DBG_NAME(OControlModel)
503cdf0e10cSrcweir //------------------------------------------------------------------
504cdf0e10cSrcweir Sequence<sal_Int8> SAL_CALL OControlModel::getImplementationId() throw(RuntimeException)
505cdf0e10cSrcweir {
506cdf0e10cSrcweir 	return OImplementationIds::getImplementationId(getTypes());
507cdf0e10cSrcweir }
508cdf0e10cSrcweir 
509cdf0e10cSrcweir //------------------------------------------------------------------
510cdf0e10cSrcweir Sequence<Type> SAL_CALL OControlModel::getTypes() throw(RuntimeException)
511cdf0e10cSrcweir {
512cdf0e10cSrcweir     TypeBag aTypes( _getTypes() );
513cdf0e10cSrcweir 
514cdf0e10cSrcweir     Reference< XTypeProvider > xProv;
515cdf0e10cSrcweir 	if ( query_aggregation( m_xAggregate, xProv ) )
516cdf0e10cSrcweir         aTypes.addTypes( xProv->getTypes() );
517cdf0e10cSrcweir 
518cdf0e10cSrcweir     return aTypes.getTypes();
519cdf0e10cSrcweir }
520cdf0e10cSrcweir 
521cdf0e10cSrcweir //------------------------------------------------------------------------------
522cdf0e10cSrcweir Sequence<Type> OControlModel::_getTypes()
523cdf0e10cSrcweir {
524cdf0e10cSrcweir     return TypeBag( OComponentHelper::getTypes(),
525cdf0e10cSrcweir         OPropertySetAggregationHelper::getTypes(),
526cdf0e10cSrcweir         OControlModel_BASE::getTypes()
527cdf0e10cSrcweir     ).getTypes();
528cdf0e10cSrcweir }
529cdf0e10cSrcweir 
530cdf0e10cSrcweir //------------------------------------------------------------------
531cdf0e10cSrcweir Any SAL_CALL OControlModel::queryAggregation(const Type& _rType) throw (RuntimeException)
532cdf0e10cSrcweir {
533cdf0e10cSrcweir 	// base class 1
534cdf0e10cSrcweir 	Any aReturn(OComponentHelper::queryAggregation(_rType));
535cdf0e10cSrcweir 
536cdf0e10cSrcweir 	// base class 2
537cdf0e10cSrcweir 	if (!aReturn.hasValue())
538cdf0e10cSrcweir 	{
539cdf0e10cSrcweir 		aReturn = OControlModel_BASE::queryInterface(_rType);
540cdf0e10cSrcweir 
541cdf0e10cSrcweir 		// our own interfaces
542cdf0e10cSrcweir 		if (!aReturn.hasValue())
543cdf0e10cSrcweir 		{
544cdf0e10cSrcweir 			aReturn = OPropertySetAggregationHelper::queryInterface(_rType);
545cdf0e10cSrcweir 			// our aggregate
546cdf0e10cSrcweir 			if (!aReturn.hasValue() && m_xAggregate.is() && !_rType.equals(::getCppuType(static_cast< Reference< XCloneable>* >(NULL))))
547cdf0e10cSrcweir 				aReturn = m_xAggregate->queryAggregation(_rType);
548cdf0e10cSrcweir 		}
549cdf0e10cSrcweir 	}
550cdf0e10cSrcweir 	return aReturn;
551cdf0e10cSrcweir }
552cdf0e10cSrcweir 
553cdf0e10cSrcweir //------------------------------------------------------------------------------
554cdf0e10cSrcweir void OControlModel::readHelpTextCompatibly(const staruno::Reference< stario::XObjectInputStream >& _rxInStream)
555cdf0e10cSrcweir {
556cdf0e10cSrcweir 	::rtl::OUString sHelpText;
557cdf0e10cSrcweir 	::comphelper::operator>>( _rxInStream, sHelpText);
558cdf0e10cSrcweir 	try
559cdf0e10cSrcweir 	{
560cdf0e10cSrcweir 		if (m_xAggregateSet.is())
561cdf0e10cSrcweir 			m_xAggregateSet->setPropertyValue(PROPERTY_HELPTEXT, makeAny(sHelpText));
562cdf0e10cSrcweir 	}
563cdf0e10cSrcweir 	catch(const Exception&)
564cdf0e10cSrcweir 	{
565cdf0e10cSrcweir 		OSL_ENSURE(sal_False, "OControlModel::readHelpTextCompatibly: could not forward the property value to the aggregate!");
566cdf0e10cSrcweir 	}
567cdf0e10cSrcweir }
568cdf0e10cSrcweir 
569cdf0e10cSrcweir //------------------------------------------------------------------------------
570cdf0e10cSrcweir void OControlModel::writeHelpTextCompatibly(const staruno::Reference< stario::XObjectOutputStream >& _rxOutStream)
571cdf0e10cSrcweir {
572cdf0e10cSrcweir 	::rtl::OUString sHelpText;
573cdf0e10cSrcweir 	try
574cdf0e10cSrcweir 	{
575cdf0e10cSrcweir 		if (m_xAggregateSet.is())
576cdf0e10cSrcweir 			m_xAggregateSet->getPropertyValue(PROPERTY_HELPTEXT) >>= sHelpText;
577cdf0e10cSrcweir 	}
578cdf0e10cSrcweir 	catch(const Exception&)
579cdf0e10cSrcweir 	{
580cdf0e10cSrcweir 		OSL_ENSURE(sal_False, "OControlModel::writeHelpTextCompatibly: could not retrieve the property value from the aggregate!");
581cdf0e10cSrcweir 	}
582cdf0e10cSrcweir 	::comphelper::operator<<( _rxOutStream, sHelpText);
583cdf0e10cSrcweir }
584cdf0e10cSrcweir 
585cdf0e10cSrcweir //------------------------------------------------------------------
586cdf0e10cSrcweir OControlModel::OControlModel(
587cdf0e10cSrcweir                         const Reference<com::sun::star::lang::XMultiServiceFactory>& _rxFactory,
588cdf0e10cSrcweir 			const ::rtl::OUString& _rUnoControlModelTypeName,
589cdf0e10cSrcweir 			const ::rtl::OUString& rDefault, const sal_Bool _bSetDelegator)
590cdf0e10cSrcweir 	:OComponentHelper(m_aMutex)
591cdf0e10cSrcweir 	,OPropertySetAggregationHelper(OComponentHelper::rBHelper)
592cdf0e10cSrcweir     ,m_aContext( _rxFactory )
593cdf0e10cSrcweir     ,m_lockCount( 0 )
594cdf0e10cSrcweir     ,m_aPropertyBagHelper( *this )
595cdf0e10cSrcweir 	,m_nTabIndex(FRM_DEFAULT_TABINDEX)
596cdf0e10cSrcweir 	,m_nClassId(FormComponentType::CONTROL)
597cdf0e10cSrcweir     ,m_bNativeLook( sal_False )
598cdf0e10cSrcweir         // form controls are usually embedded into documents, not dialogs, and in documents
599cdf0e10cSrcweir         // the native look is ugly ....
600cdf0e10cSrcweir         // #i37342# / 2004-11-19 / frank.schoenheit@sun.com
601cdf0e10cSrcweir {
602cdf0e10cSrcweir 	DBG_CTOR(OControlModel, NULL);
603cdf0e10cSrcweir 	if (_rUnoControlModelTypeName.getLength())	// the is a model we have to aggregate
604cdf0e10cSrcweir 	{
605cdf0e10cSrcweir 		increment(m_refCount);
606cdf0e10cSrcweir 
607cdf0e10cSrcweir 		{
608cdf0e10cSrcweir 			m_xAggregate = Reference<XAggregation>(_rxFactory->createInstance(_rUnoControlModelTypeName), UNO_QUERY);
609cdf0e10cSrcweir 			setAggregation(m_xAggregate);
610cdf0e10cSrcweir 
611cdf0e10cSrcweir 			if ( m_xAggregateSet.is() )
612cdf0e10cSrcweir             {
613cdf0e10cSrcweir                 try
614cdf0e10cSrcweir                 {
615cdf0e10cSrcweir                     if ( rDefault.getLength() )
616cdf0e10cSrcweir 	    			    m_xAggregateSet->setPropertyValue( PROPERTY_DEFAULTCONTROL, makeAny( rDefault ) );
617cdf0e10cSrcweir                 }
618cdf0e10cSrcweir                 catch( const Exception& )
619cdf0e10cSrcweir                 {
620cdf0e10cSrcweir                 	OSL_ENSURE( sal_False, "OControlModel::OControlModel: caught an exception!" );
621cdf0e10cSrcweir                 }
622cdf0e10cSrcweir             }
623cdf0e10cSrcweir 		}
624cdf0e10cSrcweir 
625cdf0e10cSrcweir 		if (_bSetDelegator)
626cdf0e10cSrcweir 			doSetDelegator();
627cdf0e10cSrcweir 
628cdf0e10cSrcweir 		// Refcount wieder bei NULL
629cdf0e10cSrcweir 		decrement(m_refCount);
630cdf0e10cSrcweir 	}
631cdf0e10cSrcweir }
632cdf0e10cSrcweir 
633cdf0e10cSrcweir //------------------------------------------------------------------
634cdf0e10cSrcweir OControlModel::OControlModel( const OControlModel* _pOriginal, const Reference< XMultiServiceFactory>& _rxFactory, const sal_Bool _bCloneAggregate, const sal_Bool _bSetDelegator )
635cdf0e10cSrcweir 	:OComponentHelper( m_aMutex )
636cdf0e10cSrcweir 	,OPropertySetAggregationHelper( OComponentHelper::rBHelper )
637cdf0e10cSrcweir     ,m_aContext( _rxFactory )
638cdf0e10cSrcweir     ,m_lockCount( 0 )
639cdf0e10cSrcweir     ,m_aPropertyBagHelper( *this )
640cdf0e10cSrcweir 	,m_nTabIndex( FRM_DEFAULT_TABINDEX )
641cdf0e10cSrcweir 	,m_nClassId( FormComponentType::CONTROL )
642cdf0e10cSrcweir {
643cdf0e10cSrcweir 	DBG_CTOR( OControlModel, NULL );
644cdf0e10cSrcweir 	DBG_ASSERT( _pOriginal, "OControlModel::OControlModel: invalid original!" );
645cdf0e10cSrcweir 
646cdf0e10cSrcweir 	// copy members
647cdf0e10cSrcweir 	m_aName = _pOriginal->m_aName;
648cdf0e10cSrcweir 	m_aTag = _pOriginal->m_aTag;
649cdf0e10cSrcweir 	m_nTabIndex = _pOriginal->m_nTabIndex;
650cdf0e10cSrcweir 	m_nClassId = _pOriginal->m_nClassId;
651cdf0e10cSrcweir     m_bNativeLook = _pOriginal->m_bNativeLook;
652cdf0e10cSrcweir 
653cdf0e10cSrcweir     if ( _bCloneAggregate )
654cdf0e10cSrcweir     {
655cdf0e10cSrcweir 	    // temporarily increment refcount because of temporary references to ourself in the following
656cdf0e10cSrcweir 	    increment( m_refCount );
657cdf0e10cSrcweir 
658cdf0e10cSrcweir 	    {
659cdf0e10cSrcweir 		    // transfer the (only, at the very moment!) ref count
660cdf0e10cSrcweir 		    m_xAggregate = createAggregateClone( _pOriginal );
661cdf0e10cSrcweir 
662cdf0e10cSrcweir 		    // set aggregation (retrieve other direct interfaces of the aggregate)
663cdf0e10cSrcweir 		    setAggregation( m_xAggregate );
664cdf0e10cSrcweir 	    }
665cdf0e10cSrcweir 
666cdf0e10cSrcweir 	    // set the delegator, if allowed by our derived class
667cdf0e10cSrcweir 	    if ( _bSetDelegator )
668cdf0e10cSrcweir 		    doSetDelegator();
669cdf0e10cSrcweir 
670cdf0e10cSrcweir 	    // decrement ref count
671cdf0e10cSrcweir 	    decrement( m_refCount );
672cdf0e10cSrcweir     }
673cdf0e10cSrcweir }
674cdf0e10cSrcweir 
675cdf0e10cSrcweir //------------------------------------------------------------------
676cdf0e10cSrcweir OControlModel::~OControlModel()
677cdf0e10cSrcweir {
678cdf0e10cSrcweir     // release the aggregate
679cdf0e10cSrcweir     doResetDelegator( );
680cdf0e10cSrcweir 
681cdf0e10cSrcweir     DBG_DTOR(OControlModel, NULL);
682cdf0e10cSrcweir }
683cdf0e10cSrcweir 
684cdf0e10cSrcweir //------------------------------------------------------------------
685cdf0e10cSrcweir void OControlModel::clonedFrom( const OControlModel* /*_pOriginal*/ )
686cdf0e10cSrcweir {
687cdf0e10cSrcweir     // nothing to do in this base class
688cdf0e10cSrcweir }
689cdf0e10cSrcweir 
690cdf0e10cSrcweir //------------------------------------------------------------------------------
691cdf0e10cSrcweir void OControlModel::doResetDelegator()
692cdf0e10cSrcweir {
693cdf0e10cSrcweir 	if (m_xAggregate.is())
694cdf0e10cSrcweir 		m_xAggregate->setDelegator(NULL);
695cdf0e10cSrcweir }
696cdf0e10cSrcweir 
697cdf0e10cSrcweir //------------------------------------------------------------------------------
698cdf0e10cSrcweir void OControlModel::doSetDelegator()
699cdf0e10cSrcweir {
700cdf0e10cSrcweir 	increment(m_refCount);
701cdf0e10cSrcweir 	if (m_xAggregate.is())
702cdf0e10cSrcweir 	{
703cdf0e10cSrcweir 		m_xAggregate->setDelegator(static_cast<XWeak*>(this));
704cdf0e10cSrcweir 	}
705cdf0e10cSrcweir 	decrement(m_refCount);
706cdf0e10cSrcweir }
707cdf0e10cSrcweir 
708cdf0e10cSrcweir // XChild
709cdf0e10cSrcweir //------------------------------------------------------------------------------
710cdf0e10cSrcweir Reference< XInterface > SAL_CALL OControlModel::getParent() throw(RuntimeException)
711cdf0e10cSrcweir {
712cdf0e10cSrcweir 	return m_xParent;
713cdf0e10cSrcweir }
714cdf0e10cSrcweir 
715cdf0e10cSrcweir //------------------------------------------------------------------------------
716cdf0e10cSrcweir void SAL_CALL OControlModel::setParent(const Reference< XInterface >& _rxParent) throw(com::sun::star::lang::NoSupportException, RuntimeException)
717cdf0e10cSrcweir {
718cdf0e10cSrcweir 	osl::MutexGuard aGuard(m_aMutex);
719cdf0e10cSrcweir 
720cdf0e10cSrcweir 	Reference<XComponent> xComp(m_xParent, UNO_QUERY);
721cdf0e10cSrcweir 	if (xComp.is())
722cdf0e10cSrcweir 		xComp->removeEventListener(static_cast<XPropertiesChangeListener*>(this));
723cdf0e10cSrcweir 
724cdf0e10cSrcweir 	m_xParent = _rxParent;
725cdf0e10cSrcweir 	xComp = xComp.query( m_xParent );
726cdf0e10cSrcweir 
727cdf0e10cSrcweir 	if ( xComp.is() )
728cdf0e10cSrcweir 		xComp->addEventListener(static_cast<XPropertiesChangeListener*>(this));
729cdf0e10cSrcweir }
730cdf0e10cSrcweir 
731cdf0e10cSrcweir // XNamed
732cdf0e10cSrcweir //------------------------------------------------------------------------------
733cdf0e10cSrcweir ::rtl::OUString SAL_CALL OControlModel::getName() throw(RuntimeException)
734cdf0e10cSrcweir {
735cdf0e10cSrcweir 	::rtl::OUString aReturn;
736cdf0e10cSrcweir 	OPropertySetHelper::getFastPropertyValue(PROPERTY_ID_NAME) >>= aReturn;
737cdf0e10cSrcweir 	return aReturn;
738cdf0e10cSrcweir }
739cdf0e10cSrcweir 
740cdf0e10cSrcweir //------------------------------------------------------------------------------
741cdf0e10cSrcweir void SAL_CALL OControlModel::setName(const ::rtl::OUString& _rName) throw(RuntimeException)
742cdf0e10cSrcweir {
743cdf0e10cSrcweir         setFastPropertyValue(PROPERTY_ID_NAME, makeAny(_rName));
744cdf0e10cSrcweir }
745cdf0e10cSrcweir 
746cdf0e10cSrcweir // XServiceInfo
747cdf0e10cSrcweir //------------------------------------------------------------------------------
748cdf0e10cSrcweir sal_Bool SAL_CALL OControlModel::supportsService(const rtl::OUString& _rServiceName) throw ( RuntimeException)
749cdf0e10cSrcweir {
750cdf0e10cSrcweir     Sequence<rtl::OUString> aSupported = getSupportedServiceNames();
751cdf0e10cSrcweir 	const rtl::OUString* pSupported = aSupported.getConstArray();
752cdf0e10cSrcweir 	for (sal_Int32 i=0; i<aSupported.getLength(); ++i, ++pSupported)
753cdf0e10cSrcweir 		if (pSupported->equals(_rServiceName))
754cdf0e10cSrcweir 			return sal_True;
755cdf0e10cSrcweir 	return sal_False;
756cdf0e10cSrcweir }
757cdf0e10cSrcweir 
758cdf0e10cSrcweir //------------------------------------------------------------------------------
759cdf0e10cSrcweir Sequence< ::rtl::OUString > OControlModel::getAggregateServiceNames()
760cdf0e10cSrcweir {
761cdf0e10cSrcweir     Sequence< ::rtl::OUString > aAggServices;
762cdf0e10cSrcweir     Reference< XServiceInfo > xInfo;
763cdf0e10cSrcweir 	if ( query_aggregation( m_xAggregate, xInfo ) )
764cdf0e10cSrcweir 		aAggServices = xInfo->getSupportedServiceNames();
765cdf0e10cSrcweir     return aAggServices;
766cdf0e10cSrcweir }
767cdf0e10cSrcweir 
768cdf0e10cSrcweir //------------------------------------------------------------------------------
769cdf0e10cSrcweir Sequence<rtl::OUString> SAL_CALL OControlModel::getSupportedServiceNames() throw(RuntimeException)
770cdf0e10cSrcweir {
771cdf0e10cSrcweir     return ::comphelper::concatSequences(
772cdf0e10cSrcweir         getAggregateServiceNames(),
773cdf0e10cSrcweir         getSupportedServiceNames_Static()
774cdf0e10cSrcweir     );
775cdf0e10cSrcweir }
776cdf0e10cSrcweir 
777cdf0e10cSrcweir //------------------------------------------------------------------------------
778cdf0e10cSrcweir Sequence< ::rtl::OUString > SAL_CALL OControlModel::getSupportedServiceNames_Static() throw( RuntimeException )
779cdf0e10cSrcweir {
780cdf0e10cSrcweir     Sequence< ::rtl::OUString > aServiceNames( 2 );
781cdf0e10cSrcweir 	aServiceNames[ 0 ] = FRM_SUN_FORMCOMPONENT;
782cdf0e10cSrcweir 	aServiceNames[ 1 ] = ::rtl::OUString::createFromAscii( "com.sun.star.form.FormControlModel" );
783cdf0e10cSrcweir     return aServiceNames;
784cdf0e10cSrcweir }
785cdf0e10cSrcweir 
786cdf0e10cSrcweir // XEventListener
787cdf0e10cSrcweir //------------------------------------------------------------------------------
788cdf0e10cSrcweir void SAL_CALL OControlModel::disposing(const com::sun::star::lang::EventObject& _rSource) throw (RuntimeException)
789cdf0e10cSrcweir {
790cdf0e10cSrcweir 	// release the parent
791cdf0e10cSrcweir 	if (_rSource.Source == m_xParent)
792cdf0e10cSrcweir 	{
793cdf0e10cSrcweir 		osl::MutexGuard aGuard(m_aMutex);
794cdf0e10cSrcweir 		m_xParent = NULL;
795cdf0e10cSrcweir 	}
796cdf0e10cSrcweir 	else
797cdf0e10cSrcweir 	{
798cdf0e10cSrcweir 		Reference<com::sun::star::lang::XEventListener> xEvtLst;
799cdf0e10cSrcweir 		if (query_aggregation(m_xAggregate, xEvtLst))
800cdf0e10cSrcweir 		{
801cdf0e10cSrcweir 			osl::MutexGuard aGuard(m_aMutex);
802cdf0e10cSrcweir 			xEvtLst->disposing(_rSource);
803cdf0e10cSrcweir 		}
804cdf0e10cSrcweir 	}
805cdf0e10cSrcweir }
806cdf0e10cSrcweir 
807cdf0e10cSrcweir // OComponentHelper
808cdf0e10cSrcweir //-----------------------------------------------------------------------------
809cdf0e10cSrcweir void OControlModel::disposing()
810cdf0e10cSrcweir {
811cdf0e10cSrcweir 	OPropertySetAggregationHelper::disposing();
812cdf0e10cSrcweir 
813cdf0e10cSrcweir 	Reference<com::sun::star::lang::XComponent> xComp;
814cdf0e10cSrcweir 	if (query_aggregation(m_xAggregate, xComp))
815cdf0e10cSrcweir 		xComp->dispose();
816cdf0e10cSrcweir 
817cdf0e10cSrcweir 	setParent(Reference<XFormComponent>());
818cdf0e10cSrcweir 
819cdf0e10cSrcweir     m_aPropertyBagHelper.dispose();
820cdf0e10cSrcweir }
821cdf0e10cSrcweir 
822cdf0e10cSrcweir //------------------------------------------------------------------------------
823cdf0e10cSrcweir void OControlModel::writeAggregate( const Reference< XObjectOutputStream >& _rxOutStream ) const
824cdf0e10cSrcweir {
825cdf0e10cSrcweir 	Reference< XPersistObject > xPersist;
826cdf0e10cSrcweir 	if ( query_aggregation( m_xAggregate, xPersist ) )
827cdf0e10cSrcweir 		xPersist->write( _rxOutStream );
828cdf0e10cSrcweir }
829cdf0e10cSrcweir 
830cdf0e10cSrcweir //------------------------------------------------------------------------------
831cdf0e10cSrcweir void OControlModel::readAggregate( const Reference< XObjectInputStream >& _rxInStream )
832cdf0e10cSrcweir {
833cdf0e10cSrcweir 	Reference< XPersistObject > xPersist;
834cdf0e10cSrcweir 	if ( query_aggregation( m_xAggregate, xPersist ) )
835cdf0e10cSrcweir 		xPersist->read( _rxInStream );
836cdf0e10cSrcweir }
837cdf0e10cSrcweir 
838cdf0e10cSrcweir //------------------------------------------------------------------------------
839cdf0e10cSrcweir void SAL_CALL OControlModel::write(const Reference<stario::XObjectOutputStream>& _rxOutStream)
840cdf0e10cSrcweir                         throw(stario::IOException, RuntimeException)
841cdf0e10cSrcweir {
842cdf0e10cSrcweir 	osl::MutexGuard aGuard(m_aMutex);
843cdf0e10cSrcweir 
844cdf0e10cSrcweir 	// 1. Schreiben des UnoControls
845cdf0e10cSrcweir 	Reference<stario::XMarkableStream> xMark(_rxOutStream, UNO_QUERY);
846cdf0e10cSrcweir 	if ( !xMark.is() )
847cdf0e10cSrcweir 	{
848cdf0e10cSrcweir 		throw IOException(
849cdf0e10cSrcweir 			FRM_RES_STRING( RID_STR_INVALIDSTREAM ),
850cdf0e10cSrcweir 			static_cast< ::cppu::OWeakObject* >( this )
851cdf0e10cSrcweir 		);
852cdf0e10cSrcweir 	}
853cdf0e10cSrcweir 
854cdf0e10cSrcweir 	sal_Int32 nMark = xMark->createMark();
855cdf0e10cSrcweir 	sal_Int32 nLen = 0;
856cdf0e10cSrcweir 
857cdf0e10cSrcweir 	_rxOutStream->writeLong(nLen);
858cdf0e10cSrcweir 
859cdf0e10cSrcweir     writeAggregate( _rxOutStream );
860cdf0e10cSrcweir 
861cdf0e10cSrcweir     // feststellen der Laenge
862cdf0e10cSrcweir 	nLen = xMark->offsetToMark(nMark) - 4;
863cdf0e10cSrcweir 	xMark->jumpToMark(nMark);
864cdf0e10cSrcweir 	_rxOutStream->writeLong(nLen);
865cdf0e10cSrcweir 	xMark->jumpToFurthest();
866cdf0e10cSrcweir 	xMark->deleteMark(nMark);
867cdf0e10cSrcweir 
868cdf0e10cSrcweir 	// 2. Schreiben einer VersionsNummer
869cdf0e10cSrcweir 	_rxOutStream->writeShort(0x0003);
870cdf0e10cSrcweir 
871cdf0e10cSrcweir 	// 3. Schreiben der allgemeinen Properties
872cdf0e10cSrcweir 	::comphelper::operator<<( _rxOutStream, m_aName);
873cdf0e10cSrcweir 	_rxOutStream->writeShort(m_nTabIndex);
874cdf0e10cSrcweir 	::comphelper::operator<<( _rxOutStream, m_aTag); // 3. version
875cdf0e10cSrcweir 
876cdf0e10cSrcweir 	// !!! IMPORTANT NOTE !!!
877cdf0e10cSrcweir 	// don't write any new members here : this wouldn't be compatible with older versions, as OControlModel
878cdf0e10cSrcweir 	// is a base class which is called in derived classes "read" method. So if you increment the version
879cdf0e10cSrcweir 	// and write new stuff, older office versions will read this in the _derived_ classes, which may result
880cdf0e10cSrcweir 	// in anything from data loss to crash.
881cdf0e10cSrcweir 	// !!! EOIN !!!
882cdf0e10cSrcweir }
883cdf0e10cSrcweir 
884cdf0e10cSrcweir //------------------------------------------------------------------------------
885cdf0e10cSrcweir void OControlModel::read(const Reference<stario::XObjectInputStream>& InStream) throw (::com::sun::star::io::IOException, RuntimeException)
886cdf0e10cSrcweir {
887cdf0e10cSrcweir 	osl::MutexGuard aGuard(m_aMutex);
888cdf0e10cSrcweir 
889cdf0e10cSrcweir 	Reference<stario::XMarkableStream> xMark(InStream, UNO_QUERY);
890cdf0e10cSrcweir 	if ( !xMark.is() )
891cdf0e10cSrcweir 	{
892cdf0e10cSrcweir 		throw IOException(
893cdf0e10cSrcweir 			FRM_RES_STRING( RID_STR_INVALIDSTREAM ),
894cdf0e10cSrcweir 			static_cast< ::cppu::OWeakObject* >( this )
895cdf0e10cSrcweir 		);
896cdf0e10cSrcweir 	}
897cdf0e10cSrcweir 
898cdf0e10cSrcweir 	// 1. Lesen des UnoControls
899cdf0e10cSrcweir 	sal_Int32 nLen = InStream->readLong();
900cdf0e10cSrcweir 	if (nLen)
901cdf0e10cSrcweir 	{
902cdf0e10cSrcweir 		sal_Int32 nMark = xMark->createMark();
903cdf0e10cSrcweir 
904cdf0e10cSrcweir         try
905cdf0e10cSrcweir         {
906cdf0e10cSrcweir             readAggregate( InStream );
907cdf0e10cSrcweir         }
908cdf0e10cSrcweir         catch( const Exception& )
909cdf0e10cSrcweir         {
910cdf0e10cSrcweir             DBG_UNHANDLED_EXCEPTION();
911cdf0e10cSrcweir         }
912cdf0e10cSrcweir 
913cdf0e10cSrcweir 		xMark->jumpToMark(nMark);
914cdf0e10cSrcweir 		InStream->skipBytes(nLen);
915cdf0e10cSrcweir 		xMark->deleteMark(nMark);
916cdf0e10cSrcweir 	}
917cdf0e10cSrcweir 
918cdf0e10cSrcweir 	// 2. Lesen des Versionsnummer
919cdf0e10cSrcweir 	sal_uInt16 nVersion = InStream->readShort();
920cdf0e10cSrcweir 
921cdf0e10cSrcweir 	// 3. Lesen der allgemeinen Properties
922cdf0e10cSrcweir 	::comphelper::operator>>( InStream, m_aName);
923cdf0e10cSrcweir 	m_nTabIndex  = InStream->readShort();
924cdf0e10cSrcweir 
925cdf0e10cSrcweir 	if (nVersion > 0x0002)
926cdf0e10cSrcweir 		::comphelper::operator>>( InStream, m_aTag);
927cdf0e10cSrcweir 
928cdf0e10cSrcweir 	// we had a version where we wrote the help text
929cdf0e10cSrcweir 	if (nVersion == 0x0004)
930cdf0e10cSrcweir 		readHelpTextCompatibly(InStream);
931cdf0e10cSrcweir 
932cdf0e10cSrcweir 	DBG_ASSERT(nVersion < 5, "OControlModel::read : suspicious version number !");
933cdf0e10cSrcweir 	// 4 was the version where we wrote the help text
934cdf0e10cSrcweir 	// later versions shouldn't exist (see write for a detailed comment)
935cdf0e10cSrcweir }
936cdf0e10cSrcweir 
937cdf0e10cSrcweir //------------------------------------------------------------------------------
938cdf0e10cSrcweir PropertyState OControlModel::getPropertyStateByHandle( sal_Int32 _nHandle )
939cdf0e10cSrcweir {
940cdf0e10cSrcweir 	// simply compare the current and the default value
941cdf0e10cSrcweir 	Any aCurrentValue = getPropertyDefaultByHandle( _nHandle );
942cdf0e10cSrcweir 	Any aDefaultValue;  getFastPropertyValue( aDefaultValue, _nHandle );
943cdf0e10cSrcweir 
944cdf0e10cSrcweir 	sal_Bool bEqual = uno_type_equalData(
945cdf0e10cSrcweir 			const_cast< void* >( aCurrentValue.getValue() ), aCurrentValue.getValueType().getTypeLibType(),
946cdf0e10cSrcweir 			const_cast< void* >( aDefaultValue.getValue() ), aDefaultValue.getValueType().getTypeLibType(),
947cdf0e10cSrcweir 			reinterpret_cast< uno_QueryInterfaceFunc >(cpp_queryInterface),
948cdf0e10cSrcweir             reinterpret_cast< uno_ReleaseFunc >(cpp_release)
949cdf0e10cSrcweir 		);
950cdf0e10cSrcweir     return bEqual ? PropertyState_DEFAULT_VALUE : PropertyState_DIRECT_VALUE;
951cdf0e10cSrcweir }
952cdf0e10cSrcweir 
953cdf0e10cSrcweir //------------------------------------------------------------------------------
954cdf0e10cSrcweir void OControlModel::setPropertyToDefaultByHandle( sal_Int32 _nHandle)
955cdf0e10cSrcweir {
956cdf0e10cSrcweir 	Any aDefault = getPropertyDefaultByHandle( _nHandle );
957cdf0e10cSrcweir 
958cdf0e10cSrcweir 	Any aConvertedValue, aOldValue;
959cdf0e10cSrcweir 	if ( convertFastPropertyValue( aConvertedValue, aOldValue, _nHandle, aDefault ) )
960cdf0e10cSrcweir 	{
961cdf0e10cSrcweir 		setFastPropertyValue_NoBroadcast( _nHandle, aConvertedValue );
962cdf0e10cSrcweir 		// TODO: fire the property change
963cdf0e10cSrcweir 	}
964cdf0e10cSrcweir }
965cdf0e10cSrcweir 
966cdf0e10cSrcweir //------------------------------------------------------------------------------
967cdf0e10cSrcweir Any OControlModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const
968cdf0e10cSrcweir {
969cdf0e10cSrcweir 	Any aReturn;
970cdf0e10cSrcweir 	switch ( _nHandle )
971cdf0e10cSrcweir 	{
972cdf0e10cSrcweir 		case PROPERTY_ID_NAME:
973cdf0e10cSrcweir 		case PROPERTY_ID_TAG:
974cdf0e10cSrcweir 			aReturn <<= ::rtl::OUString();
975cdf0e10cSrcweir 			break;
976cdf0e10cSrcweir 
977cdf0e10cSrcweir 		case PROPERTY_ID_CLASSID:
978cdf0e10cSrcweir 			aReturn <<= (sal_Int16)FormComponentType::CONTROL;
979cdf0e10cSrcweir 			break;
980cdf0e10cSrcweir 
981cdf0e10cSrcweir 		case PROPERTY_ID_TABINDEX:
982cdf0e10cSrcweir 			aReturn <<= (sal_Int16)FRM_DEFAULT_TABINDEX;
983cdf0e10cSrcweir 			break;
984cdf0e10cSrcweir 
985cdf0e10cSrcweir         case PROPERTY_ID_NATIVE_LOOK:
986cdf0e10cSrcweir 			aReturn <<= (sal_Bool)sal_True;
987cdf0e10cSrcweir 			break;
988cdf0e10cSrcweir 
989cdf0e10cSrcweir         default:
990cdf0e10cSrcweir             if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) )
991cdf0e10cSrcweir                 m_aPropertyBagHelper.getDynamicPropertyDefaultByHandle( _nHandle, aReturn );
992cdf0e10cSrcweir             else
993cdf0e10cSrcweir                 OSL_ENSURE( false, "OControlModel::convertFastPropertyValue: unknown handle!" );
994cdf0e10cSrcweir 	}
995cdf0e10cSrcweir 	return aReturn;
996cdf0e10cSrcweir }
997cdf0e10cSrcweir 
998cdf0e10cSrcweir //------------------------------------------------------------------------------
999cdf0e10cSrcweir void OControlModel::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const
1000cdf0e10cSrcweir {
1001cdf0e10cSrcweir 	switch ( _nHandle )
1002cdf0e10cSrcweir 	{
1003cdf0e10cSrcweir 		case PROPERTY_ID_NAME:
1004cdf0e10cSrcweir 			_rValue <<= m_aName;
1005cdf0e10cSrcweir 			break;
1006cdf0e10cSrcweir 		case PROPERTY_ID_TAG:
1007cdf0e10cSrcweir 			_rValue <<= m_aTag;
1008cdf0e10cSrcweir 			break;
1009cdf0e10cSrcweir 		case PROPERTY_ID_CLASSID:
1010cdf0e10cSrcweir 			_rValue <<= m_nClassId;
1011cdf0e10cSrcweir 			break;
1012cdf0e10cSrcweir 		case PROPERTY_ID_TABINDEX:
1013cdf0e10cSrcweir 			_rValue <<= m_nTabIndex;
1014cdf0e10cSrcweir 			break;
1015cdf0e10cSrcweir         case PROPERTY_ID_NATIVE_LOOK:
1016cdf0e10cSrcweir 			_rValue <<= (sal_Bool)m_bNativeLook;
1017cdf0e10cSrcweir 			break;
1018cdf0e10cSrcweir 		default:
1019cdf0e10cSrcweir             if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) )
1020cdf0e10cSrcweir                 m_aPropertyBagHelper.getDynamicFastPropertyValue( _nHandle, _rValue );
1021cdf0e10cSrcweir             else
1022cdf0e10cSrcweir 			    OPropertySetAggregationHelper::getFastPropertyValue( _rValue, _nHandle );
1023cdf0e10cSrcweir             break;
1024cdf0e10cSrcweir 	}
1025cdf0e10cSrcweir }
1026cdf0e10cSrcweir 
1027cdf0e10cSrcweir //------------------------------------------------------------------------------
1028cdf0e10cSrcweir sal_Bool OControlModel::convertFastPropertyValue(
1029cdf0e10cSrcweir                         Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue)
1030cdf0e10cSrcweir                         throw (com::sun::star::lang::IllegalArgumentException)
1031cdf0e10cSrcweir {
1032cdf0e10cSrcweir 	sal_Bool bModified(sal_False);
1033cdf0e10cSrcweir 	switch (_nHandle)
1034cdf0e10cSrcweir 	{
1035cdf0e10cSrcweir 		case PROPERTY_ID_NAME:
1036cdf0e10cSrcweir 			bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aName);
1037cdf0e10cSrcweir 			break;
1038cdf0e10cSrcweir 		case PROPERTY_ID_TAG:
1039cdf0e10cSrcweir 			bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aTag);
1040cdf0e10cSrcweir 			break;
1041cdf0e10cSrcweir 		case PROPERTY_ID_TABINDEX:
1042cdf0e10cSrcweir 			bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_nTabIndex);
1043cdf0e10cSrcweir 			break;
1044cdf0e10cSrcweir         case PROPERTY_ID_NATIVE_LOOK:
1045cdf0e10cSrcweir 			bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_bNativeLook);
1046cdf0e10cSrcweir 			break;
1047cdf0e10cSrcweir         default:
1048cdf0e10cSrcweir             if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) )
1049cdf0e10cSrcweir                 bModified = m_aPropertyBagHelper.convertDynamicFastPropertyValue( _nHandle, _rValue, _rConvertedValue, _rOldValue );
1050cdf0e10cSrcweir             else
1051cdf0e10cSrcweir                 OSL_ENSURE( false, "OControlModel::convertFastPropertyValue: unknown handle!" );
1052cdf0e10cSrcweir             break;
1053cdf0e10cSrcweir 	}
1054cdf0e10cSrcweir 	return bModified;
1055cdf0e10cSrcweir }
1056cdf0e10cSrcweir 
1057cdf0e10cSrcweir //------------------------------------------------------------------------------
1058cdf0e10cSrcweir void OControlModel::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const Any& _rValue)
1059cdf0e10cSrcweir                         throw (Exception)
1060cdf0e10cSrcweir {
1061cdf0e10cSrcweir 	switch (_nHandle)
1062cdf0e10cSrcweir 	{
1063cdf0e10cSrcweir 		case PROPERTY_ID_NAME:
1064cdf0e10cSrcweir 			DBG_ASSERT(_rValue.getValueType() == getCppuType((const ::rtl::OUString*)NULL),
1065cdf0e10cSrcweir 				"OControlModel::setFastPropertyValue_NoBroadcast : invalid type" );
1066cdf0e10cSrcweir 			_rValue >>= m_aName;
1067cdf0e10cSrcweir 			break;
1068cdf0e10cSrcweir 		case PROPERTY_ID_TAG:
1069cdf0e10cSrcweir 			DBG_ASSERT(_rValue.getValueType() == getCppuType((const ::rtl::OUString*)NULL),
1070cdf0e10cSrcweir 				"OControlModel::setFastPropertyValue_NoBroadcast : invalid type" );
1071cdf0e10cSrcweir 			_rValue >>= m_aTag;
1072cdf0e10cSrcweir 			break;
1073cdf0e10cSrcweir 		case PROPERTY_ID_TABINDEX:
1074cdf0e10cSrcweir 			DBG_ASSERT(_rValue.getValueType() == getCppuType((const sal_Int16*)NULL),
1075cdf0e10cSrcweir 				"OControlModel::setFastPropertyValue_NoBroadcast : invalid type" );
1076cdf0e10cSrcweir 			_rValue >>= m_nTabIndex;
1077cdf0e10cSrcweir 			break;
1078cdf0e10cSrcweir         case PROPERTY_ID_NATIVE_LOOK:
1079cdf0e10cSrcweir             OSL_VERIFY( _rValue >>= m_bNativeLook );
1080cdf0e10cSrcweir 			break;
1081cdf0e10cSrcweir         default:
1082cdf0e10cSrcweir             if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( _nHandle ) )
1083cdf0e10cSrcweir                 m_aPropertyBagHelper.setDynamicFastPropertyValue( _nHandle, _rValue );
1084cdf0e10cSrcweir             else
1085cdf0e10cSrcweir                 OSL_ENSURE( false, "OControlModel::setFastPropertyValue_NoBroadcast: unknown handle!" );
1086cdf0e10cSrcweir             break;
1087cdf0e10cSrcweir 	}
1088cdf0e10cSrcweir }
1089cdf0e10cSrcweir 
1090cdf0e10cSrcweir //------------------------------------------------------------------------------
1091cdf0e10cSrcweir void OControlModel::describeFixedProperties( Sequence< Property >& _rProps ) const
1092cdf0e10cSrcweir {
1093cdf0e10cSrcweir 	BEGIN_DESCRIBE_BASE_PROPERTIES( 4 )
1094cdf0e10cSrcweir         DECL_PROP2      (CLASSID,     sal_Int16,        READONLY, TRANSIENT);
1095cdf0e10cSrcweir         DECL_PROP1      (NAME,        ::rtl::OUString,  BOUND);
1096cdf0e10cSrcweir         DECL_BOOL_PROP2 (NATIVE_LOOK,                   BOUND, TRANSIENT);
1097cdf0e10cSrcweir         DECL_PROP1      (TAG,         ::rtl::OUString,  BOUND);
1098cdf0e10cSrcweir     END_DESCRIBE_PROPERTIES()
1099cdf0e10cSrcweir }
1100cdf0e10cSrcweir 
1101cdf0e10cSrcweir //------------------------------------------------------------------------------
1102cdf0e10cSrcweir void OControlModel::describeAggregateProperties( Sequence< Property >& /* [out] */ _rAggregateProps ) const
1103cdf0e10cSrcweir {
1104cdf0e10cSrcweir     if ( m_xAggregateSet.is() )
1105cdf0e10cSrcweir     {
1106cdf0e10cSrcweir         Reference< XPropertySetInfo > xPSI( m_xAggregateSet->getPropertySetInfo() );
1107cdf0e10cSrcweir         if ( xPSI.is() )
1108cdf0e10cSrcweir             _rAggregateProps = xPSI->getProperties();
1109cdf0e10cSrcweir     }
1110cdf0e10cSrcweir }
1111cdf0e10cSrcweir 
1112cdf0e10cSrcweir //------------------------------------------------------------------------------
1113cdf0e10cSrcweir ::osl::Mutex& OControlModel::getMutex()
1114cdf0e10cSrcweir {
1115cdf0e10cSrcweir     return m_aMutex;
1116cdf0e10cSrcweir }
1117cdf0e10cSrcweir 
1118cdf0e10cSrcweir //------------------------------------------------------------------------------
1119cdf0e10cSrcweir void OControlModel::describeFixedAndAggregateProperties( Sequence< Property >& _out_rFixedProperties, Sequence< Property >& _out_rAggregateProperties ) const
1120cdf0e10cSrcweir {
1121cdf0e10cSrcweir     describeFixedProperties( _out_rFixedProperties );
1122cdf0e10cSrcweir     describeAggregateProperties( _out_rAggregateProperties );
1123cdf0e10cSrcweir }
1124cdf0e10cSrcweir 
1125cdf0e10cSrcweir //------------------------------------------------------------------------------
1126cdf0e10cSrcweir Reference< XMultiPropertySet > OControlModel::getPropertiesInterface()
1127cdf0e10cSrcweir {
1128cdf0e10cSrcweir     return Reference< XMultiPropertySet >( *this, UNO_QUERY );
1129cdf0e10cSrcweir }
1130cdf0e10cSrcweir 
1131cdf0e10cSrcweir //------------------------------------------------------------------------------
1132cdf0e10cSrcweir Reference< XPropertySetInfo> SAL_CALL OControlModel::getPropertySetInfo() throw( RuntimeException)
1133cdf0e10cSrcweir {
1134cdf0e10cSrcweir 	return createPropertySetInfo( getInfoHelper() );
1135cdf0e10cSrcweir }
1136cdf0e10cSrcweir 
1137cdf0e10cSrcweir //------------------------------------------------------------------------------
1138cdf0e10cSrcweir ::cppu::IPropertyArrayHelper& OControlModel::getInfoHelper()
1139cdf0e10cSrcweir {
1140cdf0e10cSrcweir     return m_aPropertyBagHelper.getInfoHelper();
1141cdf0e10cSrcweir }
1142cdf0e10cSrcweir 
1143cdf0e10cSrcweir //--------------------------------------------------------------------
1144cdf0e10cSrcweir void SAL_CALL OControlModel::addProperty( const ::rtl::OUString& _rName, ::sal_Int16 _nAttributes, const Any& _rInitialValue ) throw (PropertyExistException, IllegalTypeException, IllegalArgumentException, RuntimeException)
1145cdf0e10cSrcweir {
1146cdf0e10cSrcweir     m_aPropertyBagHelper.addProperty( _rName, _nAttributes, _rInitialValue );
1147cdf0e10cSrcweir }
1148cdf0e10cSrcweir 
1149cdf0e10cSrcweir //--------------------------------------------------------------------
1150cdf0e10cSrcweir void SAL_CALL OControlModel::removeProperty( const ::rtl::OUString& _rName ) throw (UnknownPropertyException, NotRemoveableException, RuntimeException)
1151cdf0e10cSrcweir {
1152cdf0e10cSrcweir     m_aPropertyBagHelper.removeProperty( _rName );
1153cdf0e10cSrcweir }
1154cdf0e10cSrcweir 
1155cdf0e10cSrcweir //--------------------------------------------------------------------
1156cdf0e10cSrcweir Sequence< PropertyValue > SAL_CALL OControlModel::getPropertyValues() throw (RuntimeException)
1157cdf0e10cSrcweir {
1158cdf0e10cSrcweir     return m_aPropertyBagHelper.getPropertyValues();
1159cdf0e10cSrcweir }
1160cdf0e10cSrcweir 
1161cdf0e10cSrcweir //--------------------------------------------------------------------
1162cdf0e10cSrcweir void SAL_CALL OControlModel::setPropertyValues( const Sequence< PropertyValue >& _rProps ) throw (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
1163cdf0e10cSrcweir {
1164cdf0e10cSrcweir     m_aPropertyBagHelper.setPropertyValues( _rProps );
1165cdf0e10cSrcweir }
1166cdf0e10cSrcweir 
1167cdf0e10cSrcweir //--------------------------------------------------------------------
1168cdf0e10cSrcweir void OControlModel::lockInstance( LockAccess )
1169cdf0e10cSrcweir {
1170cdf0e10cSrcweir     m_aMutex.acquire();
1171cdf0e10cSrcweir     osl_incrementInterlockedCount( &m_lockCount );
1172cdf0e10cSrcweir }
1173cdf0e10cSrcweir 
1174cdf0e10cSrcweir //--------------------------------------------------------------------
1175cdf0e10cSrcweir oslInterlockedCount OControlModel::unlockInstance( LockAccess )
1176cdf0e10cSrcweir {
1177cdf0e10cSrcweir     OSL_ENSURE( m_lockCount > 0, "OControlModel::unlockInstance: not locked!" );
1178cdf0e10cSrcweir     oslInterlockedCount lockCount = osl_decrementInterlockedCount( &m_lockCount );
1179cdf0e10cSrcweir     m_aMutex.release();
1180cdf0e10cSrcweir     return lockCount;
1181cdf0e10cSrcweir }
1182cdf0e10cSrcweir 
1183cdf0e10cSrcweir //--------------------------------------------------------------------
1184cdf0e10cSrcweir void OControlModel::firePropertyChanges( const Sequence< sal_Int32 >& _rHandles, const Sequence< Any >& _rOldValues,
1185cdf0e10cSrcweir                                         const Sequence< Any >& _rNewValues, LockAccess )
1186cdf0e10cSrcweir {
1187cdf0e10cSrcweir     OPropertySetHelper::fire(
1188cdf0e10cSrcweir         const_cast< Sequence< sal_Int32 >& >( _rHandles ).getArray(),
1189cdf0e10cSrcweir         _rNewValues.getConstArray(),
1190cdf0e10cSrcweir         _rOldValues.getConstArray(),
1191cdf0e10cSrcweir         _rHandles.getLength(),
1192cdf0e10cSrcweir         sal_False
1193cdf0e10cSrcweir     );
1194cdf0e10cSrcweir }
1195cdf0e10cSrcweir 
1196cdf0e10cSrcweir //==================================================================
1197cdf0e10cSrcweir //= OBoundControlModel
1198cdf0e10cSrcweir //==================================================================
1199cdf0e10cSrcweir DBG_NAME(frm_OBoundControlModel);
1200cdf0e10cSrcweir //------------------------------------------------------------------
1201cdf0e10cSrcweir Any SAL_CALL OBoundControlModel::queryAggregation( const Type& _rType ) throw (RuntimeException)
1202cdf0e10cSrcweir {
1203cdf0e10cSrcweir 	Any aReturn( OControlModel::queryAggregation(_rType) );
1204cdf0e10cSrcweir 	if (!aReturn.hasValue())
1205cdf0e10cSrcweir 	{
1206cdf0e10cSrcweir 		aReturn = OBoundControlModel_BASE1::queryInterface(_rType);
1207cdf0e10cSrcweir 
1208cdf0e10cSrcweir         if ( !aReturn.hasValue() && m_bCommitable )
1209cdf0e10cSrcweir 			aReturn = OBoundControlModel_COMMITTING::queryInterface( _rType );
1210cdf0e10cSrcweir 
1211cdf0e10cSrcweir         if ( !aReturn.hasValue() && m_bSupportsExternalBinding )
1212cdf0e10cSrcweir 			aReturn = OBoundControlModel_BINDING::queryInterface( _rType );
1213cdf0e10cSrcweir 
1214cdf0e10cSrcweir         if ( !aReturn.hasValue() && m_bSupportsValidation )
1215cdf0e10cSrcweir 			aReturn = OBoundControlModel_VALIDATION::queryInterface( _rType );
1216cdf0e10cSrcweir 	}
1217cdf0e10cSrcweir 
1218cdf0e10cSrcweir 	return aReturn;
1219cdf0e10cSrcweir }
1220cdf0e10cSrcweir 
1221cdf0e10cSrcweir //------------------------------------------------------------------
1222cdf0e10cSrcweir OBoundControlModel::OBoundControlModel(
1223cdf0e10cSrcweir         const Reference< XMultiServiceFactory>& _rxFactory,
1224cdf0e10cSrcweir 		const ::rtl::OUString& _rUnoControlModelTypeName, const ::rtl::OUString& _rDefault,
1225cdf0e10cSrcweir 		const sal_Bool _bCommitable, const sal_Bool _bSupportExternalBinding, const sal_Bool _bSupportsValidation )
1226cdf0e10cSrcweir 	:OControlModel( _rxFactory, _rUnoControlModelTypeName, _rDefault, sal_False )
1227cdf0e10cSrcweir 	,OPropertyChangeListener( m_aMutex )
1228cdf0e10cSrcweir     ,m_xField()
1229cdf0e10cSrcweir     ,m_xAmbientForm()
1230cdf0e10cSrcweir     ,m_nValuePropertyAggregateHandle( -1 )
1231cdf0e10cSrcweir     ,m_nFieldType( DataType::OTHER )
1232cdf0e10cSrcweir     ,m_bValuePropertyMayBeVoid( false )
1233cdf0e10cSrcweir     ,m_aResetHelper( *this, m_aMutex )
1234cdf0e10cSrcweir     ,m_aUpdateListeners(m_aMutex)
1235cdf0e10cSrcweir     ,m_aFormComponentListeners( m_aMutex )
1236cdf0e10cSrcweir     ,m_bInputRequired( sal_True )
1237cdf0e10cSrcweir     ,m_pAggPropMultiplexer( NULL )
1238cdf0e10cSrcweir     ,m_bFormListening( false )
1239cdf0e10cSrcweir     ,m_bLoaded(sal_False)
1240cdf0e10cSrcweir     ,m_bRequired(sal_False)
1241cdf0e10cSrcweir 	,m_bCommitable(_bCommitable)
1242cdf0e10cSrcweir     ,m_bSupportsExternalBinding( _bSupportExternalBinding )
1243cdf0e10cSrcweir     ,m_bSupportsValidation( _bSupportsValidation )
1244cdf0e10cSrcweir     ,m_bForwardValueChanges(sal_True)
1245cdf0e10cSrcweir     ,m_bTransferingValue( sal_False )
1246cdf0e10cSrcweir     ,m_bIsCurrentValueValid( sal_True )
1247cdf0e10cSrcweir     ,m_bBindingControlsRO( sal_False )
1248cdf0e10cSrcweir     ,m_bBindingControlsEnable( sal_False )
1249cdf0e10cSrcweir 	,m_eControlValueChangeInstigator( eOther )
1250cdf0e10cSrcweir     ,m_aLabelServiceName(FRM_SUN_COMPONENT_FIXEDTEXT)
1251cdf0e10cSrcweir {
1252cdf0e10cSrcweir 	DBG_CTOR(frm_OBoundControlModel, NULL);
1253cdf0e10cSrcweir 
1254cdf0e10cSrcweir     // start property listening at the aggregate
1255cdf0e10cSrcweir     implInitAggMultiplexer( );
1256cdf0e10cSrcweir }
1257cdf0e10cSrcweir 
1258cdf0e10cSrcweir //------------------------------------------------------------------
1259cdf0e10cSrcweir OBoundControlModel::OBoundControlModel(
1260cdf0e10cSrcweir 		const OBoundControlModel* _pOriginal, const Reference< XMultiServiceFactory>& _rxFactory )
1261cdf0e10cSrcweir 	:OControlModel( _pOriginal, _rxFactory, sal_True, sal_False )
1262cdf0e10cSrcweir 	,OPropertyChangeListener( m_aMutex )
1263cdf0e10cSrcweir     ,m_xField()
1264cdf0e10cSrcweir     ,m_xAmbientForm()
1265cdf0e10cSrcweir     ,m_nValuePropertyAggregateHandle( _pOriginal->m_nValuePropertyAggregateHandle )
1266cdf0e10cSrcweir     ,m_nFieldType( DataType::OTHER )
1267cdf0e10cSrcweir     ,m_bValuePropertyMayBeVoid( _pOriginal->m_bValuePropertyMayBeVoid )
1268cdf0e10cSrcweir     ,m_aResetHelper( *this, m_aMutex )
1269cdf0e10cSrcweir     ,m_aUpdateListeners( m_aMutex )
1270cdf0e10cSrcweir     ,m_aFormComponentListeners( m_aMutex )
1271cdf0e10cSrcweir     ,m_xValidator( _pOriginal->m_xValidator )
1272cdf0e10cSrcweir     ,m_bInputRequired( sal_True )
1273cdf0e10cSrcweir     ,m_pAggPropMultiplexer( NULL )
1274cdf0e10cSrcweir     ,m_bFormListening( false )
1275cdf0e10cSrcweir     ,m_bLoaded( sal_False )
1276cdf0e10cSrcweir 	,m_bRequired( sal_False )
1277cdf0e10cSrcweir 	,m_bCommitable( _pOriginal->m_bCommitable )
1278cdf0e10cSrcweir     ,m_bSupportsExternalBinding( _pOriginal->m_bSupportsExternalBinding )
1279cdf0e10cSrcweir     ,m_bSupportsValidation( _pOriginal->m_bSupportsValidation )
1280cdf0e10cSrcweir 	,m_bForwardValueChanges( sal_True )
1281cdf0e10cSrcweir     ,m_bTransferingValue( sal_False )
1282cdf0e10cSrcweir     ,m_bIsCurrentValueValid( _pOriginal->m_bIsCurrentValueValid )
1283cdf0e10cSrcweir     ,m_bBindingControlsRO( sal_False )
1284cdf0e10cSrcweir     ,m_bBindingControlsEnable( sal_False )
1285cdf0e10cSrcweir     ,m_eControlValueChangeInstigator( eOther )
1286cdf0e10cSrcweir {
1287cdf0e10cSrcweir 	DBG_CTOR(frm_OBoundControlModel, NULL);
1288cdf0e10cSrcweir 
1289cdf0e10cSrcweir     // start property listening at the aggregate
1290cdf0e10cSrcweir     implInitAggMultiplexer( );
1291cdf0e10cSrcweir 
1292cdf0e10cSrcweir 	m_aLabelServiceName = _pOriginal->m_aLabelServiceName;
1293cdf0e10cSrcweir 	m_sValuePropertyName = _pOriginal->m_sValuePropertyName;
1294cdf0e10cSrcweir     m_nValuePropertyAggregateHandle = _pOriginal->m_nValuePropertyAggregateHandle;
1295cdf0e10cSrcweir     m_bValuePropertyMayBeVoid = _pOriginal->m_bValuePropertyMayBeVoid;
1296cdf0e10cSrcweir     m_aValuePropertyType = _pOriginal->m_aValuePropertyType;
1297cdf0e10cSrcweir 	m_aControlSource = _pOriginal->m_aControlSource;
1298cdf0e10cSrcweir 	m_bInputRequired = _pOriginal->m_bInputRequired;
1299cdf0e10cSrcweir 	// m_xLabelControl, though being a property, is not to be cloned, not even the reference will be transfered.
1300cdf0e10cSrcweir 	// (the former should be clear - a clone of the object we're only referencing does not make sense)
1301cdf0e10cSrcweir 	// (the second would violate the restriction for label controls that they're part of the
1302cdf0e10cSrcweir 	// same form component hierarchy - we ourself are no part, yet, so we can't have a label control)
1303cdf0e10cSrcweir 
1304cdf0e10cSrcweir     // start listening for changes at the value property
1305cdf0e10cSrcweir     implInitValuePropertyListening( );
1306cdf0e10cSrcweir }
1307cdf0e10cSrcweir 
1308cdf0e10cSrcweir //------------------------------------------------------------------
1309cdf0e10cSrcweir OBoundControlModel::~OBoundControlModel()
1310cdf0e10cSrcweir {
1311cdf0e10cSrcweir 	if ( !OComponentHelper::rBHelper.bDisposed )
1312cdf0e10cSrcweir 	{
1313cdf0e10cSrcweir 		acquire();
1314cdf0e10cSrcweir 		dispose();
1315cdf0e10cSrcweir 	}
1316cdf0e10cSrcweir 
1317cdf0e10cSrcweir     doResetDelegator( );
1318cdf0e10cSrcweir 
1319cdf0e10cSrcweir     OSL_ENSURE( m_pAggPropMultiplexer, "OBoundControlModel::~OBoundControlModel: what about my property multiplexer?" );
1320cdf0e10cSrcweir 	if ( m_pAggPropMultiplexer )
1321cdf0e10cSrcweir 	{
1322cdf0e10cSrcweir 		m_pAggPropMultiplexer->dispose();
1323cdf0e10cSrcweir 		m_pAggPropMultiplexer->release();
1324cdf0e10cSrcweir 		m_pAggPropMultiplexer = NULL;
1325cdf0e10cSrcweir 	}
1326cdf0e10cSrcweir 
1327cdf0e10cSrcweir     DBG_DTOR(frm_OBoundControlModel, NULL);
1328cdf0e10cSrcweir }
1329cdf0e10cSrcweir 
1330cdf0e10cSrcweir //------------------------------------------------------------------
1331cdf0e10cSrcweir void OBoundControlModel::clonedFrom( const OControlModel* _pOriginal )
1332cdf0e10cSrcweir {
1333cdf0e10cSrcweir     const OBoundControlModel* pBoundOriginal = static_cast< const OBoundControlModel* >( _pOriginal );
1334cdf0e10cSrcweir     // the value binding can be handled as if somebody called setValueBinding here
1335cdf0e10cSrcweir     // By definition, bindings can be share between bindables
1336cdf0e10cSrcweir     if ( pBoundOriginal && pBoundOriginal->m_xExternalBinding.is() )
1337cdf0e10cSrcweir     {
1338cdf0e10cSrcweir         try
1339cdf0e10cSrcweir         {
1340cdf0e10cSrcweir             setValueBinding( pBoundOriginal->m_xExternalBinding );
1341cdf0e10cSrcweir         }
1342cdf0e10cSrcweir         catch( const Exception& )
1343cdf0e10cSrcweir         {
1344cdf0e10cSrcweir         	DBG_UNHANDLED_EXCEPTION();
1345cdf0e10cSrcweir         }
1346cdf0e10cSrcweir     }
1347cdf0e10cSrcweir }
1348cdf0e10cSrcweir 
1349cdf0e10cSrcweir //-----------------------------------------------------------------------------
1350cdf0e10cSrcweir void OBoundControlModel::implInitAggMultiplexer( )
1351cdf0e10cSrcweir {
1352cdf0e10cSrcweir 	increment( m_refCount );
1353cdf0e10cSrcweir 	if ( m_xAggregateSet.is() )
1354cdf0e10cSrcweir 	{
1355cdf0e10cSrcweir 		m_pAggPropMultiplexer = new OPropertyChangeMultiplexer( this, m_xAggregateSet, sal_False );
1356cdf0e10cSrcweir 		m_pAggPropMultiplexer->acquire();
1357cdf0e10cSrcweir 	}
1358cdf0e10cSrcweir 	decrement( m_refCount );
1359cdf0e10cSrcweir 
1360cdf0e10cSrcweir    	doSetDelegator();
1361cdf0e10cSrcweir }
1362cdf0e10cSrcweir 
1363cdf0e10cSrcweir //-----------------------------------------------------------------------------
1364cdf0e10cSrcweir void OBoundControlModel::implInitValuePropertyListening( ) const
1365cdf0e10cSrcweir {
1366cdf0e10cSrcweir     // start listening for changes at the value property
1367cdf0e10cSrcweir     // There are three pre-requisites for this to be done:
1368cdf0e10cSrcweir     // 1. We support external value bindings. In this case, the changes in the control value need to
1369cdf0e10cSrcweir     //    be propagated to the external binding immediately when they happen
1370cdf0e10cSrcweir     // 2. We support external validation. In this case, we need to listen for changes in the value
1371cdf0e10cSrcweir     //    property, since we need to revalidate then.
1372cdf0e10cSrcweir     // 3. We are not committable. In this case, changes in the control value need to be propagated
1373cdf0e10cSrcweir     //    to the database column immediately when they happen.
1374cdf0e10cSrcweir     if ( m_bSupportsExternalBinding || m_bSupportsValidation || !m_bCommitable )
1375cdf0e10cSrcweir     {
1376cdf0e10cSrcweir         OSL_ENSURE( m_pAggPropMultiplexer, "OBoundControlModel::implInitValuePropertyListening: no multiplexer!" );
1377cdf0e10cSrcweir         if ( m_pAggPropMultiplexer && m_sValuePropertyName.getLength() )
1378cdf0e10cSrcweir             m_pAggPropMultiplexer->addProperty( m_sValuePropertyName );
1379cdf0e10cSrcweir     }
1380cdf0e10cSrcweir }
1381cdf0e10cSrcweir 
1382cdf0e10cSrcweir //-----------------------------------------------------------------------------
1383cdf0e10cSrcweir void OBoundControlModel::initOwnValueProperty( const ::rtl::OUString& i_rValuePropertyName )
1384cdf0e10cSrcweir {
1385cdf0e10cSrcweir     OSL_PRECOND( !m_sValuePropertyName.getLength() && -1 == m_nValuePropertyAggregateHandle,
1386cdf0e10cSrcweir         "OBoundControlModel::initOwnValueProperty: value property is already initialized!" );
1387cdf0e10cSrcweir     OSL_ENSURE( i_rValuePropertyName.getLength(), "OBoundControlModel::initOwnValueProperty: invalid property name!" );
1388cdf0e10cSrcweir     m_sValuePropertyName = i_rValuePropertyName;
1389cdf0e10cSrcweir }
1390cdf0e10cSrcweir 
1391cdf0e10cSrcweir //-----------------------------------------------------------------------------
1392cdf0e10cSrcweir void OBoundControlModel::initValueProperty( const ::rtl::OUString& _rValuePropertyName, sal_Int32 _nValuePropertyExternalHandle )
1393cdf0e10cSrcweir {
1394cdf0e10cSrcweir     OSL_PRECOND( !m_sValuePropertyName.getLength() && -1 == m_nValuePropertyAggregateHandle,
1395cdf0e10cSrcweir         "OBoundControlModel::initValueProperty: value property is already initialized!" );
1396cdf0e10cSrcweir     OSL_ENSURE( _rValuePropertyName.getLength(), "OBoundControlModel::initValueProperty: invalid property name!" );
1397cdf0e10cSrcweir     OSL_ENSURE( _nValuePropertyExternalHandle != -1, "OBoundControlModel::initValueProperty: invalid property handle!" );
1398cdf0e10cSrcweir 
1399cdf0e10cSrcweir     m_sValuePropertyName = _rValuePropertyName;
1400cdf0e10cSrcweir 	m_nValuePropertyAggregateHandle = getOriginalHandle( _nValuePropertyExternalHandle );
1401cdf0e10cSrcweir     OSL_ENSURE( m_nValuePropertyAggregateHandle != -1, "OBoundControlModel::initValueProperty: unable to find the original handle!" );
1402cdf0e10cSrcweir 
1403cdf0e10cSrcweir     if ( m_nValuePropertyAggregateHandle != -1 )
1404cdf0e10cSrcweir     {
1405cdf0e10cSrcweir         Reference< XPropertySetInfo > xPropInfo( m_xAggregateSet->getPropertySetInfo(), UNO_SET_THROW );
1406cdf0e10cSrcweir         Property aValuePropDesc = xPropInfo->getPropertyByName( m_sValuePropertyName );
1407cdf0e10cSrcweir         m_aValuePropertyType = aValuePropDesc.Type;
1408cdf0e10cSrcweir         m_bValuePropertyMayBeVoid = ( aValuePropDesc.Attributes & PropertyAttribute::MAYBEVOID ) != 0;
1409cdf0e10cSrcweir     }
1410cdf0e10cSrcweir 
1411cdf0e10cSrcweir     // start listening for changes at the value property
1412cdf0e10cSrcweir     implInitValuePropertyListening( );
1413cdf0e10cSrcweir }
1414cdf0e10cSrcweir 
1415cdf0e10cSrcweir //-----------------------------------------------------------------------------
1416cdf0e10cSrcweir void OBoundControlModel::suspendValueListening( )
1417cdf0e10cSrcweir {
1418cdf0e10cSrcweir     OSL_PRECOND( m_sValuePropertyName.getLength(), "OBoundControlModel::suspendValueListening: don't have a value property!" );
1419cdf0e10cSrcweir     OSL_PRECOND( m_pAggPropMultiplexer, "OBoundControlModel::suspendValueListening: I *am* not listening!" );
1420cdf0e10cSrcweir 
1421cdf0e10cSrcweir     if ( m_pAggPropMultiplexer )
1422cdf0e10cSrcweir         m_pAggPropMultiplexer->lock();
1423cdf0e10cSrcweir }
1424cdf0e10cSrcweir 
1425cdf0e10cSrcweir //-----------------------------------------------------------------------------
1426cdf0e10cSrcweir void OBoundControlModel::resumeValueListening( )
1427cdf0e10cSrcweir {
1428cdf0e10cSrcweir     OSL_PRECOND( m_sValuePropertyName.getLength(), "OBoundControlModel::resumeValueListening: don't have a value property!" );
1429cdf0e10cSrcweir     OSL_PRECOND( m_pAggPropMultiplexer, "OBoundControlModel::resumeValueListening: I *am* not listening at all!" );
1430cdf0e10cSrcweir     OSL_PRECOND( !m_pAggPropMultiplexer || m_pAggPropMultiplexer->locked(), "OBoundControlModel::resumeValueListening: listening not suspended currently!" );
1431cdf0e10cSrcweir 
1432cdf0e10cSrcweir     if ( m_pAggPropMultiplexer )
1433cdf0e10cSrcweir         m_pAggPropMultiplexer->unlock();
1434cdf0e10cSrcweir }
1435cdf0e10cSrcweir 
1436cdf0e10cSrcweir //-----------------------------------------------------------------------------
1437cdf0e10cSrcweir Sequence< Type > OBoundControlModel::_getTypes()
1438cdf0e10cSrcweir {
1439cdf0e10cSrcweir     TypeBag aTypes(
1440cdf0e10cSrcweir         OControlModel::_getTypes(),
1441cdf0e10cSrcweir         OBoundControlModel_BASE1::getTypes()
1442cdf0e10cSrcweir     );
1443cdf0e10cSrcweir 
1444cdf0e10cSrcweir 	if ( m_bCommitable )
1445cdf0e10cSrcweir         aTypes.addTypes( OBoundControlModel_COMMITTING::getTypes() );
1446cdf0e10cSrcweir 
1447cdf0e10cSrcweir 	if ( m_bSupportsExternalBinding )
1448cdf0e10cSrcweir         aTypes.addTypes( OBoundControlModel_BINDING::getTypes() );
1449cdf0e10cSrcweir 
1450cdf0e10cSrcweir     if ( m_bSupportsValidation )
1451cdf0e10cSrcweir         aTypes.addTypes( OBoundControlModel_VALIDATION::getTypes() );
1452cdf0e10cSrcweir 
1453cdf0e10cSrcweir 	return aTypes.getTypes();
1454cdf0e10cSrcweir }
1455cdf0e10cSrcweir 
1456cdf0e10cSrcweir // OComponentHelper
1457cdf0e10cSrcweir //-----------------------------------------------------------------------------
1458cdf0e10cSrcweir void OBoundControlModel::disposing()
1459cdf0e10cSrcweir {
1460cdf0e10cSrcweir 	OControlModel::disposing();
1461cdf0e10cSrcweir 
1462cdf0e10cSrcweir     ::osl::ClearableMutexGuard aGuard(m_aMutex);
1463cdf0e10cSrcweir 
1464cdf0e10cSrcweir 	if ( m_pAggPropMultiplexer )
1465cdf0e10cSrcweir 		m_pAggPropMultiplexer->dispose();
1466cdf0e10cSrcweir 
1467cdf0e10cSrcweir     // notify all our listeners
1468cdf0e10cSrcweir     com::sun::star::lang::EventObject aEvt( static_cast< XWeak* >( this ) );
1469cdf0e10cSrcweir 	m_aUpdateListeners.disposeAndClear( aEvt );
1470cdf0e10cSrcweir     m_aResetHelper.disposing();
1471cdf0e10cSrcweir 
1472cdf0e10cSrcweir     // disconnect from our database column
1473cdf0e10cSrcweir     // TODO: could we replace the following 5 lines with a call to impl_disconnectDatabaseColumn_noNotify?
1474cdf0e10cSrcweir     // The only more thing which it does is calling onDisconnectedDbColumn - could this
1475cdf0e10cSrcweir     // cause trouble? At least when we continue to call OControlModel::disposing before, it *may*.
1476cdf0e10cSrcweir 	if ( hasField() )
1477cdf0e10cSrcweir 	{
1478cdf0e10cSrcweir 		getField()->removePropertyChangeListener( PROPERTY_VALUE, this );
1479cdf0e10cSrcweir 		resetField();
1480cdf0e10cSrcweir 	}
1481cdf0e10cSrcweir 	m_xCursor = NULL;
1482cdf0e10cSrcweir 
1483cdf0e10cSrcweir     Reference< XComponent > xComp( m_xLabelControl, UNO_QUERY );
1484cdf0e10cSrcweir 	if ( xComp.is() )
1485cdf0e10cSrcweir         xComp->removeEventListener(static_cast< XEventListener* >( static_cast< XPropertyChangeListener* >( this ) ) );
1486cdf0e10cSrcweir 
1487cdf0e10cSrcweir     // disconnect from our external value binding
1488cdf0e10cSrcweir     if ( hasExternalValueBinding() )
1489cdf0e10cSrcweir         disconnectExternalValueBinding();
1490cdf0e10cSrcweir 
1491cdf0e10cSrcweir     // dito for the validator
1492cdf0e10cSrcweir     if ( hasValidator() )
1493cdf0e10cSrcweir         disconnectValidator( );
1494cdf0e10cSrcweir }
1495cdf0e10cSrcweir 
1496cdf0e10cSrcweir //------------------------------------------------------------------------------
1497cdf0e10cSrcweir void OBoundControlModel::onValuePropertyChange( ControlModelLock& i_rControLock )
1498cdf0e10cSrcweir {
1499cdf0e10cSrcweir     if ( hasExternalValueBinding() )
1500cdf0e10cSrcweir     {   // the control value changed, while we have an external value binding
1501cdf0e10cSrcweir         // -> forward the value to it
1502cdf0e10cSrcweir         if ( m_eControlValueChangeInstigator != eExternalBinding )
1503cdf0e10cSrcweir             transferControlValueToExternal( i_rControLock );
1504cdf0e10cSrcweir     }
1505cdf0e10cSrcweir     else if ( !m_bCommitable && m_xColumnUpdate.is() )
1506cdf0e10cSrcweir     {   // the control value changed, while we are  bound to a database column,
1507cdf0e10cSrcweir         // but not committable (which means changes in the control have to be reflected to
1508cdf0e10cSrcweir         // the underlying database column immediately)
1509cdf0e10cSrcweir         // -> forward the value to the database column
1510cdf0e10cSrcweir         if ( m_eControlValueChangeInstigator != eDbColumnBinding )
1511cdf0e10cSrcweir             commitControlValueToDbColumn( false );
1512cdf0e10cSrcweir     }
1513cdf0e10cSrcweir 
1514cdf0e10cSrcweir     // validate the new value
1515cdf0e10cSrcweir     if ( m_bSupportsValidation )
1516cdf0e10cSrcweir         recheckValidity( true );
1517cdf0e10cSrcweir }
1518cdf0e10cSrcweir 
1519cdf0e10cSrcweir //------------------------------------------------------------------------------
1520cdf0e10cSrcweir void OBoundControlModel::_propertyChanged( const PropertyChangeEvent& _rEvt ) throw ( RuntimeException )
1521cdf0e10cSrcweir {
1522cdf0e10cSrcweir     ControlModelLock aLock( *this );
1523cdf0e10cSrcweir 
1524cdf0e10cSrcweir     OSL_ENSURE( _rEvt.PropertyName == m_sValuePropertyName,
1525cdf0e10cSrcweir         "OBoundControlModel::_propertyChanged: where did this come from (1)?" );
1526cdf0e10cSrcweir     OSL_ENSURE( m_pAggPropMultiplexer && !m_pAggPropMultiplexer->locked(),
1527cdf0e10cSrcweir         "OBoundControlModel::_propertyChanged: where did this come from (2)?" );
1528cdf0e10cSrcweir 
1529cdf0e10cSrcweir     if ( _rEvt.PropertyName == m_sValuePropertyName )
1530cdf0e10cSrcweir     {
1531cdf0e10cSrcweir         onValuePropertyChange( aLock );
1532cdf0e10cSrcweir     }
1533cdf0e10cSrcweir }
1534cdf0e10cSrcweir 
1535cdf0e10cSrcweir //------------------------------------------------------------------------------
1536cdf0e10cSrcweir void OBoundControlModel::startAggregatePropertyListening( const ::rtl::OUString& _rPropertyName )
1537cdf0e10cSrcweir {
1538cdf0e10cSrcweir     OSL_PRECOND( m_pAggPropMultiplexer, "OBoundControlModel::startAggregatePropertyListening: no multiplexer!" );
1539cdf0e10cSrcweir     OSL_ENSURE( _rPropertyName.getLength(), "OBoundControlModel::startAggregatePropertyListening: invalid property name!" );
1540cdf0e10cSrcweir 
1541cdf0e10cSrcweir     if ( m_pAggPropMultiplexer && _rPropertyName.getLength() )
1542cdf0e10cSrcweir     {
1543cdf0e10cSrcweir         m_pAggPropMultiplexer->addProperty( _rPropertyName );
1544cdf0e10cSrcweir     }
1545cdf0e10cSrcweir }
1546cdf0e10cSrcweir 
1547cdf0e10cSrcweir //------------------------------------------------------------------------------
1548cdf0e10cSrcweir void OBoundControlModel::doFormListening( const bool _bStart )
1549cdf0e10cSrcweir {
1550cdf0e10cSrcweir     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::doFormListening: external value binding should overrule the database binding!" );
1551cdf0e10cSrcweir 
1552cdf0e10cSrcweir     if ( isFormListening() == _bStart )
1553cdf0e10cSrcweir         return;
1554cdf0e10cSrcweir 
1555cdf0e10cSrcweir 	if ( m_xAmbientForm.is() )
1556cdf0e10cSrcweir         _bStart ? m_xAmbientForm->addLoadListener( this ) : m_xAmbientForm->removeLoadListener( this );
1557cdf0e10cSrcweir 
1558cdf0e10cSrcweir     Reference< XLoadable > xParentLoadable( getParent(), UNO_QUERY );
1559cdf0e10cSrcweir     if ( getParent().is() && !xParentLoadable.is() )
1560cdf0e10cSrcweir     {
1561cdf0e10cSrcweir         // if our parent does not directly support the XLoadable interface, then it might support the
1562cdf0e10cSrcweir         // XRowSetSupplier/XRowSetChangeBroadcaster interfaces. In this case we have to listen for changes
1563cdf0e10cSrcweir         // broadcasted by the latter.
1564cdf0e10cSrcweir         Reference< XRowSetChangeBroadcaster > xRowSetBroadcaster( getParent(), UNO_QUERY );
1565cdf0e10cSrcweir         if ( xRowSetBroadcaster.is() )
1566cdf0e10cSrcweir             _bStart ? xRowSetBroadcaster->addRowSetChangeListener( this ) : xRowSetBroadcaster->removeRowSetChangeListener( this );
1567cdf0e10cSrcweir     }
1568cdf0e10cSrcweir 
1569cdf0e10cSrcweir     m_bFormListening = _bStart && m_xAmbientForm.is();
1570cdf0e10cSrcweir }
1571cdf0e10cSrcweir 
1572cdf0e10cSrcweir // XChild
1573cdf0e10cSrcweir //------------------------------------------------------------------------------
1574cdf0e10cSrcweir void SAL_CALL OBoundControlModel::setParent(const Reference<XInterface>& _rxParent) throw(com::sun::star::lang::NoSupportException, RuntimeException)
1575cdf0e10cSrcweir {
1576cdf0e10cSrcweir     ControlModelLock aLock( *this );
1577cdf0e10cSrcweir     FieldChangeNotifier aBoundFieldNotifier( aLock );
1578cdf0e10cSrcweir 
1579cdf0e10cSrcweir     if ( getParent() == _rxParent )
1580cdf0e10cSrcweir         return;
1581cdf0e10cSrcweir 
1582cdf0e10cSrcweir     // disconnect from database column (which is controlled by parent, directly or indirectly)
1583cdf0e10cSrcweir     if ( hasField() )
1584cdf0e10cSrcweir         impl_disconnectDatabaseColumn_noNotify();
1585cdf0e10cSrcweir 
1586cdf0e10cSrcweir 	// log off old listeners
1587cdf0e10cSrcweir     if ( isFormListening() )
1588cdf0e10cSrcweir         doFormListening( false );
1589cdf0e10cSrcweir 
1590cdf0e10cSrcweir     // actually set the new parent
1591cdf0e10cSrcweir 	OControlModel::setParent( _rxParent );
1592cdf0e10cSrcweir 
1593cdf0e10cSrcweir     // a new parent means a new ambient form
1594cdf0e10cSrcweir     impl_determineAmbientForm_nothrow();
1595cdf0e10cSrcweir 
1596cdf0e10cSrcweir     if ( !hasExternalValueBinding() )
1597cdf0e10cSrcweir     {
1598cdf0e10cSrcweir         // log on new listeners
1599cdf0e10cSrcweir         doFormListening( true );
1600cdf0e10cSrcweir 
1601cdf0e10cSrcweir         // re-connect to database column of the new parent
1602cdf0e10cSrcweir         if ( m_xAmbientForm.is() && m_xAmbientForm->isLoaded() )
1603cdf0e10cSrcweir             impl_connectDatabaseColumn_noNotify( false );
1604cdf0e10cSrcweir     }
1605cdf0e10cSrcweir }
1606cdf0e10cSrcweir 
1607cdf0e10cSrcweir // XEventListener
1608cdf0e10cSrcweir //------------------------------------------------------------------------------
1609cdf0e10cSrcweir void SAL_CALL OBoundControlModel::disposing(const com::sun::star::lang::EventObject& _rEvent) throw (RuntimeException)
1610cdf0e10cSrcweir {
1611cdf0e10cSrcweir     ControlModelLock aLock( *this );
1612cdf0e10cSrcweir 
1613cdf0e10cSrcweir     if ( _rEvent.Source == getField() )
1614cdf0e10cSrcweir 	{
1615cdf0e10cSrcweir 		resetField();
1616cdf0e10cSrcweir 	}
1617cdf0e10cSrcweir 	else if ( _rEvent.Source == m_xLabelControl )
1618cdf0e10cSrcweir 	{
1619cdf0e10cSrcweir 		Reference<XPropertySet> xOldValue = m_xLabelControl;
1620cdf0e10cSrcweir 		m_xLabelControl = NULL;
1621cdf0e10cSrcweir 
1622cdf0e10cSrcweir         // fire a propertyChanged (when we leave aLock's scope)
1623cdf0e10cSrcweir         aLock.addPropertyNotification( PROPERTY_ID_CONTROLLABEL, makeAny( xOldValue ), makeAny( m_xLabelControl ) );
1624cdf0e10cSrcweir 	}
1625cdf0e10cSrcweir 	else if ( _rEvent.Source == m_xExternalBinding )
1626cdf0e10cSrcweir     {   // *first* check for the external binding
1627cdf0e10cSrcweir         disconnectExternalValueBinding( );
1628cdf0e10cSrcweir     }
1629cdf0e10cSrcweir     else if ( _rEvent.Source == m_xValidator )
1630cdf0e10cSrcweir     {   // *then* check for the validator. Reason is that bindings may also act as validator at the same
1631cdf0e10cSrcweir         // time, in this case, the validator is automatically revoked when the binding is revoked
1632cdf0e10cSrcweir         disconnectValidator( );
1633cdf0e10cSrcweir     }
1634cdf0e10cSrcweir     else
1635cdf0e10cSrcweir 		OControlModel::disposing(_rEvent);
1636cdf0e10cSrcweir }
1637cdf0e10cSrcweir 
1638cdf0e10cSrcweir // XServiceInfo
1639cdf0e10cSrcweir //------------------------------------------------------------------------------
1640cdf0e10cSrcweir StringSequence SAL_CALL OBoundControlModel::getSupportedServiceNames() throw(RuntimeException)
1641cdf0e10cSrcweir {
1642cdf0e10cSrcweir     return ::comphelper::concatSequences(
1643cdf0e10cSrcweir         getAggregateServiceNames(),
1644cdf0e10cSrcweir         getSupportedServiceNames_Static()
1645cdf0e10cSrcweir     );
1646cdf0e10cSrcweir }
1647cdf0e10cSrcweir 
1648cdf0e10cSrcweir //------------------------------------------------------------------------------
1649cdf0e10cSrcweir Sequence< ::rtl::OUString > SAL_CALL OBoundControlModel::getSupportedServiceNames_Static() throw( RuntimeException )
1650cdf0e10cSrcweir {
1651cdf0e10cSrcweir     Sequence< ::rtl::OUString > aOwnServiceNames( 1 );
1652cdf0e10cSrcweir 	aOwnServiceNames[ 0 ] = ::rtl::OUString::createFromAscii( "com.sun.star.form.DataAwareControlModel" );
1653cdf0e10cSrcweir 
1654cdf0e10cSrcweir     return ::comphelper::concatSequences(
1655cdf0e10cSrcweir         OControlModel::getSupportedServiceNames_Static(),
1656cdf0e10cSrcweir         aOwnServiceNames
1657cdf0e10cSrcweir     );
1658cdf0e10cSrcweir }
1659cdf0e10cSrcweir 
1660cdf0e10cSrcweir // XPersist
1661cdf0e10cSrcweir //------------------------------------------------------------------------------
1662cdf0e10cSrcweir void SAL_CALL OBoundControlModel::write( const Reference<stario::XObjectOutputStream>& _rxOutStream ) throw(stario::IOException, RuntimeException)
1663cdf0e10cSrcweir {
1664cdf0e10cSrcweir 	OControlModel::write(_rxOutStream);
1665cdf0e10cSrcweir 
1666cdf0e10cSrcweir 	osl::MutexGuard aGuard(m_aMutex);
1667cdf0e10cSrcweir 
1668cdf0e10cSrcweir 	// Version
1669cdf0e10cSrcweir 	_rxOutStream->writeShort(0x0002);
1670cdf0e10cSrcweir 
1671cdf0e10cSrcweir 	// Controlsource
1672cdf0e10cSrcweir 	::comphelper::operator<<( _rxOutStream, m_aControlSource);
1673cdf0e10cSrcweir 
1674cdf0e10cSrcweir 	// !!! IMPORTANT NOTE !!!
1675cdf0e10cSrcweir 	// don't write any new members here : this wouldn't be compatible with older versions, as OBoundControlModel
1676cdf0e10cSrcweir 	// is a base class which is called in derived classes "read" method. So if you increment the version
1677cdf0e10cSrcweir 	// and write new stuff, older office versions will read this in the _derived_ classes, which may result
1678cdf0e10cSrcweir 	// in anything from data loss to crash.
1679cdf0e10cSrcweir 	// (use writeCommonProperties instead, this is called in derived classes write-method)
1680cdf0e10cSrcweir 	// !!! EOIN !!!
1681cdf0e10cSrcweir 	// FS - 68876 - 28.09.1999
1682cdf0e10cSrcweir }
1683cdf0e10cSrcweir 
1684cdf0e10cSrcweir //------------------------------------------------------------------------------
1685cdf0e10cSrcweir void OBoundControlModel::defaultCommonProperties()
1686cdf0e10cSrcweir {
1687cdf0e10cSrcweir     Reference<com::sun::star::lang::XComponent> xComp(m_xLabelControl, UNO_QUERY);
1688cdf0e10cSrcweir 	if (xComp.is())
1689cdf0e10cSrcweir         xComp->removeEventListener(static_cast<com::sun::star::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this)));
1690cdf0e10cSrcweir 	m_xLabelControl = NULL;
1691cdf0e10cSrcweir }
1692cdf0e10cSrcweir 
1693cdf0e10cSrcweir //------------------------------------------------------------------------------
1694cdf0e10cSrcweir void OBoundControlModel::readCommonProperties(const Reference<stario::XObjectInputStream>& _rxInStream)
1695cdf0e10cSrcweir {
1696cdf0e10cSrcweir 	sal_Int32 nLen = _rxInStream->readLong();
1697cdf0e10cSrcweir 
1698cdf0e10cSrcweir     Reference<stario::XMarkableStream> xMark(_rxInStream, UNO_QUERY);
1699cdf0e10cSrcweir 	DBG_ASSERT(xMark.is(), "OBoundControlModel::readCommonProperties : can only work with markable streams !");
1700cdf0e10cSrcweir 	sal_Int32 nMark = xMark->createMark();
1701cdf0e10cSrcweir 
1702cdf0e10cSrcweir 	// read the reference to the label control
1703cdf0e10cSrcweir     Reference<stario::XPersistObject> xPersist;
1704cdf0e10cSrcweir 	sal_Int32 nUsedFlag;
1705cdf0e10cSrcweir 	nUsedFlag = _rxInStream->readLong();
1706cdf0e10cSrcweir 	if (nUsedFlag)
1707cdf0e10cSrcweir 		xPersist = _rxInStream->readObject();
1708cdf0e10cSrcweir     m_xLabelControl = m_xLabelControl.query( xPersist );
1709cdf0e10cSrcweir     Reference< XComponent > xComp( m_xLabelControl, UNO_QUERY );
1710cdf0e10cSrcweir 	if (xComp.is())
1711cdf0e10cSrcweir         xComp->addEventListener(static_cast<com::sun::star::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this)));
1712cdf0e10cSrcweir 
1713cdf0e10cSrcweir 	// read any other new common properties here
1714cdf0e10cSrcweir 
1715cdf0e10cSrcweir 	// skip the remaining bytes
1716cdf0e10cSrcweir 	xMark->jumpToMark(nMark);
1717cdf0e10cSrcweir 	_rxInStream->skipBytes(nLen);
1718cdf0e10cSrcweir 	xMark->deleteMark(nMark);
1719cdf0e10cSrcweir }
1720cdf0e10cSrcweir 
1721cdf0e10cSrcweir //------------------------------------------------------------------------------
1722cdf0e10cSrcweir void OBoundControlModel::writeCommonProperties(const Reference<stario::XObjectOutputStream>& _rxOutStream)
1723cdf0e10cSrcweir {
1724cdf0e10cSrcweir     Reference<stario::XMarkableStream> xMark(_rxOutStream, UNO_QUERY);
1725cdf0e10cSrcweir 	DBG_ASSERT(xMark.is(), "OBoundControlModel::writeCommonProperties : can only work with markable streams !");
1726cdf0e10cSrcweir 	sal_Int32 nMark = xMark->createMark();
1727cdf0e10cSrcweir 
1728cdf0e10cSrcweir 	// a placeholder where we will write the overall length (later in this method)
1729cdf0e10cSrcweir 	sal_Int32 nLen = 0;
1730cdf0e10cSrcweir 	_rxOutStream->writeLong(nLen);
1731cdf0e10cSrcweir 
1732cdf0e10cSrcweir 	// write the reference to the label control
1733cdf0e10cSrcweir     Reference<stario::XPersistObject> xPersist(m_xLabelControl, UNO_QUERY);
1734cdf0e10cSrcweir 	sal_Int32 nUsedFlag = 0;
1735cdf0e10cSrcweir 	if (xPersist.is())
1736cdf0e10cSrcweir 		nUsedFlag = 1;
1737cdf0e10cSrcweir 	_rxOutStream->writeLong(nUsedFlag);
1738cdf0e10cSrcweir 	if (xPersist.is())
1739cdf0e10cSrcweir 		_rxOutStream->writeObject(xPersist);
1740cdf0e10cSrcweir 
1741cdf0e10cSrcweir 	// write any other new common properties here
1742cdf0e10cSrcweir 
1743cdf0e10cSrcweir 	// write the correct length at the beginning of the block
1744cdf0e10cSrcweir 	nLen = xMark->offsetToMark(nMark) - sizeof(nLen);
1745cdf0e10cSrcweir 	xMark->jumpToMark(nMark);
1746cdf0e10cSrcweir 	_rxOutStream->writeLong(nLen);
1747cdf0e10cSrcweir 	xMark->jumpToFurthest();
1748cdf0e10cSrcweir 	xMark->deleteMark(nMark);
1749cdf0e10cSrcweir }
1750cdf0e10cSrcweir 
1751cdf0e10cSrcweir //------------------------------------------------------------------------------
1752cdf0e10cSrcweir void SAL_CALL OBoundControlModel::read( const Reference< stario::XObjectInputStream >& _rxInStream ) throw(stario::IOException, RuntimeException)
1753cdf0e10cSrcweir {
1754cdf0e10cSrcweir 	OControlModel::read(_rxInStream);
1755cdf0e10cSrcweir 
1756cdf0e10cSrcweir 	osl::MutexGuard aGuard(m_aMutex);
1757cdf0e10cSrcweir 	sal_uInt16 nVersion = _rxInStream->readShort(); (void)nVersion;
1758cdf0e10cSrcweir 	::comphelper::operator>>( _rxInStream, m_aControlSource);
1759cdf0e10cSrcweir }
1760cdf0e10cSrcweir 
1761cdf0e10cSrcweir //------------------------------------------------------------------------------
1762cdf0e10cSrcweir void OBoundControlModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const
1763cdf0e10cSrcweir {
1764cdf0e10cSrcweir 	switch (nHandle)
1765cdf0e10cSrcweir 	{
1766cdf0e10cSrcweir         case PROPERTY_ID_INPUT_REQUIRED:
1767cdf0e10cSrcweir             rValue <<= m_bInputRequired;
1768cdf0e10cSrcweir             break;
1769cdf0e10cSrcweir 		case PROPERTY_ID_CONTROLSOURCEPROPERTY:
1770cdf0e10cSrcweir 			rValue <<= m_sValuePropertyName;
1771cdf0e10cSrcweir 			break;
1772cdf0e10cSrcweir 		case PROPERTY_ID_CONTROLSOURCE:
1773cdf0e10cSrcweir 			rValue <<= m_aControlSource;
1774cdf0e10cSrcweir 			break;
1775cdf0e10cSrcweir 		case PROPERTY_ID_BOUNDFIELD:
1776cdf0e10cSrcweir 			rValue <<= getField();
1777cdf0e10cSrcweir 			break;
1778cdf0e10cSrcweir 		case PROPERTY_ID_CONTROLLABEL:
1779cdf0e10cSrcweir 			if (!m_xLabelControl.is())
1780cdf0e10cSrcweir 				rValue.clear();
1781cdf0e10cSrcweir 			else
1782cdf0e10cSrcweir 				rValue <<= m_xLabelControl;
1783cdf0e10cSrcweir 			break;
1784cdf0e10cSrcweir 		default:
1785cdf0e10cSrcweir 			OControlModel::getFastPropertyValue(rValue, nHandle);
1786cdf0e10cSrcweir 	}
1787cdf0e10cSrcweir }
1788cdf0e10cSrcweir 
1789cdf0e10cSrcweir //------------------------------------------------------------------------------
1790cdf0e10cSrcweir sal_Bool OBoundControlModel::convertFastPropertyValue(
1791cdf0e10cSrcweir                                 Any& _rConvertedValue, Any& _rOldValue,
1792cdf0e10cSrcweir 				sal_Int32 _nHandle,
1793cdf0e10cSrcweir                                 const Any& _rValue)
1794cdf0e10cSrcweir                 throw (com::sun::star::lang::IllegalArgumentException)
1795cdf0e10cSrcweir {
1796cdf0e10cSrcweir 	sal_Bool bModified(sal_False);
1797cdf0e10cSrcweir 	switch (_nHandle)
1798cdf0e10cSrcweir 	{
1799cdf0e10cSrcweir         case PROPERTY_ID_INPUT_REQUIRED:
1800cdf0e10cSrcweir             bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_bInputRequired );
1801cdf0e10cSrcweir             break;
1802cdf0e10cSrcweir 		case PROPERTY_ID_CONTROLSOURCE:
1803cdf0e10cSrcweir 			bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aControlSource);
1804cdf0e10cSrcweir 			break;
1805cdf0e10cSrcweir 		case PROPERTY_ID_BOUNDFIELD:
1806cdf0e10cSrcweir 			DBG_ERROR( "OBoundControlModel::convertFastPropertyValue: BoundField should be a read-only property !" );
1807cdf0e10cSrcweir             throw com::sun::star::lang::IllegalArgumentException();
1808cdf0e10cSrcweir 		case PROPERTY_ID_CONTROLLABEL:
1809cdf0e10cSrcweir 			if (!_rValue.hasValue())
1810cdf0e10cSrcweir 			{	// property set to void
1811cdf0e10cSrcweir                 _rConvertedValue = Any();
1812cdf0e10cSrcweir 				getFastPropertyValue(_rOldValue, _nHandle);
1813cdf0e10cSrcweir 				bModified = m_xLabelControl.is();
1814cdf0e10cSrcweir 			}
1815cdf0e10cSrcweir 			else
1816cdf0e10cSrcweir 			{
1817cdf0e10cSrcweir 				bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_xLabelControl);
1818cdf0e10cSrcweir 				if (!m_xLabelControl.is())
1819cdf0e10cSrcweir 					// an empty interface is interpreted as VOID
1820cdf0e10cSrcweir 					_rOldValue.clear();
1821cdf0e10cSrcweir 			}
1822cdf0e10cSrcweir 			break;
1823cdf0e10cSrcweir 		default:
1824cdf0e10cSrcweir 			bModified = OControlModel::convertFastPropertyValue(_rConvertedValue, _rOldValue, _nHandle, _rValue);
1825cdf0e10cSrcweir 	}
1826cdf0e10cSrcweir 	return bModified;
1827cdf0e10cSrcweir }
1828cdf0e10cSrcweir 
1829cdf0e10cSrcweir //------------------------------------------------------------------------------
1830cdf0e10cSrcweir Any OBoundControlModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const
1831cdf0e10cSrcweir {
1832cdf0e10cSrcweir     Any aDefault;
1833cdf0e10cSrcweir     switch ( _nHandle )
1834cdf0e10cSrcweir     {
1835cdf0e10cSrcweir         case PROPERTY_ID_INPUT_REQUIRED:
1836cdf0e10cSrcweir 			aDefault <<= sal_Bool( sal_True );
1837cdf0e10cSrcweir             break;
1838cdf0e10cSrcweir 
1839cdf0e10cSrcweir 		case PROPERTY_ID_CONTROLSOURCE:
1840cdf0e10cSrcweir             aDefault <<= ::rtl::OUString();
1841cdf0e10cSrcweir 			break;
1842cdf0e10cSrcweir 
1843cdf0e10cSrcweir         case PROPERTY_ID_CONTROLLABEL:
1844cdf0e10cSrcweir             aDefault <<= Reference< XPropertySet >();
1845cdf0e10cSrcweir             break;
1846cdf0e10cSrcweir     }
1847cdf0e10cSrcweir     return aDefault;
1848cdf0e10cSrcweir }
1849cdf0e10cSrcweir 
1850cdf0e10cSrcweir //------------------------------------------------------------------------------
1851cdf0e10cSrcweir void OBoundControlModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw (Exception)
1852cdf0e10cSrcweir {
1853cdf0e10cSrcweir 	switch (nHandle)
1854cdf0e10cSrcweir 	{
1855cdf0e10cSrcweir         case PROPERTY_ID_INPUT_REQUIRED:
1856cdf0e10cSrcweir 			OSL_VERIFY( rValue >>= m_bInputRequired );
1857cdf0e10cSrcweir             break;
1858cdf0e10cSrcweir 		case PROPERTY_ID_CONTROLSOURCE:
1859cdf0e10cSrcweir 			OSL_VERIFY( rValue >>= m_aControlSource );
1860cdf0e10cSrcweir 			break;
1861cdf0e10cSrcweir 		case PROPERTY_ID_BOUNDFIELD:
1862cdf0e10cSrcweir 			DBG_ERROR("OBoundControlModel::setFastPropertyValue_NoBroadcast : BoundField should be a read-only property !");
1863cdf0e10cSrcweir             throw com::sun::star::lang::IllegalArgumentException();
1864cdf0e10cSrcweir 		case PROPERTY_ID_CONTROLLABEL:
1865cdf0e10cSrcweir 		{
1866cdf0e10cSrcweir             if ( rValue.hasValue() && ( rValue.getValueTypeClass() != TypeClass_INTERFACE ) )
1867cdf0e10cSrcweir 				throw com::sun::star::lang::IllegalArgumentException();
1868cdf0e10cSrcweir 
1869cdf0e10cSrcweir             Reference< XInterface > xNewValue( rValue, UNO_QUERY );
1870cdf0e10cSrcweir 			if ( !xNewValue.is() )
1871cdf0e10cSrcweir 			{	// set property to "void"
1872cdf0e10cSrcweir                 Reference< XComponent > xComp( m_xLabelControl, UNO_QUERY );
1873cdf0e10cSrcweir 				if ( xComp.is() )
1874cdf0e10cSrcweir                     xComp->removeEventListener( static_cast< XPropertyChangeListener* >( this ) );
1875cdf0e10cSrcweir 				m_xLabelControl = NULL;
1876cdf0e10cSrcweir 				break;
1877cdf0e10cSrcweir 			}
1878cdf0e10cSrcweir 
1879cdf0e10cSrcweir             Reference< XControlModel >  xAsModel        ( xNewValue,        UNO_QUERY );
1880cdf0e10cSrcweir             Reference< XServiceInfo >   xAsServiceInfo  ( xAsModel,         UNO_QUERY );
1881cdf0e10cSrcweir             Reference< XPropertySet >   xAsPropSet      ( xAsServiceInfo,   UNO_QUERY );
1882cdf0e10cSrcweir             Reference< XChild >         xAsChild        ( xAsPropSet,       UNO_QUERY );
1883cdf0e10cSrcweir             if ( !xAsChild.is() || !xAsServiceInfo->supportsService( m_aLabelServiceName ) )
1884cdf0e10cSrcweir             {
1885cdf0e10cSrcweir 				throw com::sun::star::lang::IllegalArgumentException();
1886cdf0e10cSrcweir             }
1887cdf0e10cSrcweir 
1888cdf0e10cSrcweir 			// check if weself and the given model have a common anchestor (up to the forms collection)
1889cdf0e10cSrcweir             Reference<XChild> xCont;
1890cdf0e10cSrcweir             query_interface(static_cast<XWeak*>(this), xCont);
1891cdf0e10cSrcweir 			Reference< XInterface > xMyTopLevel = xCont->getParent();
1892cdf0e10cSrcweir 			while (xMyTopLevel.is())
1893cdf0e10cSrcweir 			{
1894cdf0e10cSrcweir                 Reference<XForm> xAsForm(xMyTopLevel, UNO_QUERY);
1895cdf0e10cSrcweir 				if (!xAsForm.is())
1896cdf0e10cSrcweir 					// found my root
1897cdf0e10cSrcweir 					break;
1898cdf0e10cSrcweir 
1899cdf0e10cSrcweir                 Reference<XChild> xLoopAsChild(xMyTopLevel, UNO_QUERY);
1900cdf0e10cSrcweir 				xMyTopLevel = xLoopAsChild.is() ? xLoopAsChild->getParent() : Reference< XInterface >();
1901cdf0e10cSrcweir 			}
1902cdf0e10cSrcweir 			Reference< XInterface > xNewTopLevel = xAsChild->getParent();
1903cdf0e10cSrcweir 			while (xNewTopLevel.is())
1904cdf0e10cSrcweir 			{
1905cdf0e10cSrcweir                 Reference<XForm> xAsForm(xNewTopLevel, UNO_QUERY);
1906cdf0e10cSrcweir 				if (!xAsForm.is())
1907cdf0e10cSrcweir 					break;
1908cdf0e10cSrcweir 
1909cdf0e10cSrcweir                 Reference<XChild> xLoopAsChild(xNewTopLevel, UNO_QUERY);
1910cdf0e10cSrcweir 				xNewTopLevel = xLoopAsChild.is() ? xLoopAsChild->getParent() : Reference< XInterface >();
1911cdf0e10cSrcweir 			}
1912cdf0e10cSrcweir 			if (xNewTopLevel != xMyTopLevel)
1913cdf0e10cSrcweir 			{
1914cdf0e10cSrcweir 				// the both objects don't belong to the same forms collection -> not acceptable
1915cdf0e10cSrcweir                 throw com::sun::star::lang::IllegalArgumentException();
1916cdf0e10cSrcweir 			}
1917cdf0e10cSrcweir 
1918cdf0e10cSrcweir 			m_xLabelControl = xAsPropSet;
1919cdf0e10cSrcweir             Reference<com::sun::star::lang::XComponent> xComp(m_xLabelControl, UNO_QUERY);
1920cdf0e10cSrcweir 			if (xComp.is())
1921cdf0e10cSrcweir                 xComp->addEventListener(static_cast<com::sun::star::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this)));
1922cdf0e10cSrcweir 		}
1923cdf0e10cSrcweir 		break;
1924cdf0e10cSrcweir 		default:
1925cdf0e10cSrcweir 			OControlModel::setFastPropertyValue_NoBroadcast(nHandle, rValue );
1926cdf0e10cSrcweir 	}
1927cdf0e10cSrcweir }
1928cdf0e10cSrcweir 
1929cdf0e10cSrcweir // XPropertyChangeListener
1930cdf0e10cSrcweir //------------------------------------------------------------------------------
1931cdf0e10cSrcweir void SAL_CALL OBoundControlModel::propertyChange( const PropertyChangeEvent& evt ) throw(RuntimeException)
1932cdf0e10cSrcweir {
1933cdf0e10cSrcweir 	// if the DBColumn value changed, transfer it to the control
1934cdf0e10cSrcweir 	if ( evt.PropertyName.equals( PROPERTY_VALUE ) )
1935cdf0e10cSrcweir 	{
1936cdf0e10cSrcweir         OSL_ENSURE( evt.Source == getField(), "OBoundControlModel::propertyChange: value changes from components other than our database colum?" );
1937cdf0e10cSrcweir 		osl::MutexGuard aGuard(m_aMutex);
1938cdf0e10cSrcweir 		if ( m_bForwardValueChanges && m_xColumn.is() )
1939cdf0e10cSrcweir 			transferDbValueToControl();
1940cdf0e10cSrcweir 	}
1941cdf0e10cSrcweir     else
1942cdf0e10cSrcweir     {
1943cdf0e10cSrcweir         OSL_ENSURE( evt.Source == m_xExternalBinding, "OBoundControlModel::propertyChange: where did this come from?" );
1944cdf0e10cSrcweir 
1945cdf0e10cSrcweir         // our binding has properties which can control properties of ourself
1946cdf0e10cSrcweir         ::rtl::OUString sBindingControlledProperty;
1947cdf0e10cSrcweir         bool bForwardToLabelControl = false;
1948cdf0e10cSrcweir         if ( evt.PropertyName.equals( PROPERTY_READONLY ) )
1949cdf0e10cSrcweir         {
1950cdf0e10cSrcweir             sBindingControlledProperty = PROPERTY_READONLY;
1951cdf0e10cSrcweir         }
1952cdf0e10cSrcweir         else if ( evt.PropertyName.equals( PROPERTY_RELEVANT ) )
1953cdf0e10cSrcweir         {
1954cdf0e10cSrcweir             sBindingControlledProperty = PROPERTY_ENABLED;
1955cdf0e10cSrcweir             bForwardToLabelControl = true;
1956cdf0e10cSrcweir         }
1957cdf0e10cSrcweir         else
1958cdf0e10cSrcweir             return;
1959cdf0e10cSrcweir 
1960cdf0e10cSrcweir         try
1961cdf0e10cSrcweir         {
1962cdf0e10cSrcweir             setPropertyValue( sBindingControlledProperty, evt.NewValue );
1963cdf0e10cSrcweir             if ( bForwardToLabelControl && m_xLabelControl.is() )
1964cdf0e10cSrcweir                 m_xLabelControl->setPropertyValue( sBindingControlledProperty, evt.NewValue );
1965cdf0e10cSrcweir         }
1966cdf0e10cSrcweir         catch( const Exception& )
1967cdf0e10cSrcweir         {
1968cdf0e10cSrcweir         	OSL_ENSURE( sal_False, "OBoundControlModel::propertyChange: could not adjust my binding-controlled property!" );
1969cdf0e10cSrcweir         }
1970cdf0e10cSrcweir     }
1971cdf0e10cSrcweir }
1972cdf0e10cSrcweir 
1973cdf0e10cSrcweir //------------------------------------------------------------------------------
1974cdf0e10cSrcweir void SAL_CALL OBoundControlModel::onRowSetChanged( const EventObject& /*i_Event*/ ) throw (RuntimeException)
1975cdf0e10cSrcweir {
1976cdf0e10cSrcweir     ControlModelLock aLock( *this );
1977cdf0e10cSrcweir     FieldChangeNotifier aBoundFieldNotifier( aLock );
1978cdf0e10cSrcweir 
1979cdf0e10cSrcweir     // disconnect from database column (which is controlled by parent, directly or indirectly)
1980cdf0e10cSrcweir     if ( hasField() )
1981cdf0e10cSrcweir         impl_disconnectDatabaseColumn_noNotify();
1982cdf0e10cSrcweir 
1983cdf0e10cSrcweir 	// log off old listeners
1984cdf0e10cSrcweir     if ( isFormListening() )
1985cdf0e10cSrcweir         doFormListening( false );
1986cdf0e10cSrcweir 
1987cdf0e10cSrcweir     // determine the new ambient form
1988cdf0e10cSrcweir     impl_determineAmbientForm_nothrow();
1989cdf0e10cSrcweir 
1990cdf0e10cSrcweir     // log on new listeners
1991cdf0e10cSrcweir     doFormListening( true );
1992cdf0e10cSrcweir 
1993cdf0e10cSrcweir     // re-connect to database column if needed and possible
1994cdf0e10cSrcweir     if ( m_xAmbientForm.is() && m_xAmbientForm->isLoaded() )
1995cdf0e10cSrcweir         impl_connectDatabaseColumn_noNotify( false );
1996cdf0e10cSrcweir }
1997cdf0e10cSrcweir 
1998cdf0e10cSrcweir // XBoundComponent
1999cdf0e10cSrcweir //------------------------------------------------------------------------------
2000cdf0e10cSrcweir void SAL_CALL OBoundControlModel::addUpdateListener(const Reference<XUpdateListener>& _rxListener) throw(RuntimeException)
2001cdf0e10cSrcweir {
2002cdf0e10cSrcweir 	m_aUpdateListeners.addInterface(_rxListener);
2003cdf0e10cSrcweir }
2004cdf0e10cSrcweir 
2005cdf0e10cSrcweir //------------------------------------------------------------------------------
2006cdf0e10cSrcweir void SAL_CALL OBoundControlModel::removeUpdateListener(const Reference< XUpdateListener>& _rxListener) throw(RuntimeException)
2007cdf0e10cSrcweir {
2008cdf0e10cSrcweir 	m_aUpdateListeners.removeInterface(_rxListener);
2009cdf0e10cSrcweir }
2010cdf0e10cSrcweir 
2011cdf0e10cSrcweir //------------------------------------------------------------------------------
2012cdf0e10cSrcweir sal_Bool SAL_CALL OBoundControlModel::commit() throw(RuntimeException)
2013cdf0e10cSrcweir {
2014cdf0e10cSrcweir     ControlModelLock aLock( *this );
2015cdf0e10cSrcweir 
2016cdf0e10cSrcweir     OSL_PRECOND( m_bCommitable, "OBoundControlModel::commit: invalid call (I'm not commitable !) " );
2017cdf0e10cSrcweir     if ( hasExternalValueBinding() )
2018cdf0e10cSrcweir     {
2019cdf0e10cSrcweir         // in most cases, no action is required: For most derivees, we know the value property of
2020cdf0e10cSrcweir         // our control (see initValueProperty), and when an external binding is active, we
2021cdf0e10cSrcweir         // instantly forward all changes in this property to the external binding.
2022cdf0e10cSrcweir         if ( !m_sValuePropertyName.getLength() )
2023cdf0e10cSrcweir             // but for those derivees which did not use this feature, we need an
2024cdf0e10cSrcweir             // explicit transfer
2025cdf0e10cSrcweir             transferControlValueToExternal( aLock );
2026cdf0e10cSrcweir         return sal_True;
2027cdf0e10cSrcweir     }
2028cdf0e10cSrcweir 
2029cdf0e10cSrcweir     OSL_ENSURE( !hasExternalValueBinding(), "OBoundControlModel::commit: control flow broken!" );
2030cdf0e10cSrcweir         // we reach this only if we're not working with an external binding
2031cdf0e10cSrcweir 
2032cdf0e10cSrcweir 	if ( !hasField() )
2033cdf0e10cSrcweir 		return sal_True;
2034cdf0e10cSrcweir 
2035cdf0e10cSrcweir     ::cppu::OInterfaceIteratorHelper aIter( m_aUpdateListeners );
2036cdf0e10cSrcweir     EventObject aEvent;
2037cdf0e10cSrcweir     aEvent.Source = static_cast< XWeak* >( this );
2038cdf0e10cSrcweir 	sal_Bool bSuccess = sal_True;
2039cdf0e10cSrcweir 
2040cdf0e10cSrcweir     aLock.release();
2041cdf0e10cSrcweir     // >>>>>>>> ----- UNSAFE ----- >>>>>>>>
2042cdf0e10cSrcweir 	while (aIter.hasMoreElements() && bSuccess)
2043cdf0e10cSrcweir         bSuccess = static_cast< XUpdateListener* >( aIter.next() )->approveUpdate( aEvent );
2044cdf0e10cSrcweir     // <<<<<<<< ----- UNSAFE ----- <<<<<<<<
2045cdf0e10cSrcweir     aLock.acquire();
2046cdf0e10cSrcweir 
2047cdf0e10cSrcweir 	if ( bSuccess )
2048cdf0e10cSrcweir 	{
2049cdf0e10cSrcweir 		try
2050cdf0e10cSrcweir 		{
2051cdf0e10cSrcweir             if ( m_xColumnUpdate.is() )
2052cdf0e10cSrcweir                 bSuccess = commitControlValueToDbColumn( sal_False );
2053cdf0e10cSrcweir 		}
2054cdf0e10cSrcweir 		catch(Exception&)
2055cdf0e10cSrcweir 		{
2056cdf0e10cSrcweir 			bSuccess = sal_False;
2057cdf0e10cSrcweir 		}
2058cdf0e10cSrcweir 	}
2059cdf0e10cSrcweir 
2060cdf0e10cSrcweir 	if ( bSuccess )
2061cdf0e10cSrcweir     {
2062cdf0e10cSrcweir         aLock.release();
2063cdf0e10cSrcweir         m_aUpdateListeners.notifyEach( &XUpdateListener::updated, aEvent );
2064cdf0e10cSrcweir     }
2065cdf0e10cSrcweir 
2066cdf0e10cSrcweir 	return bSuccess;
2067cdf0e10cSrcweir }
2068cdf0e10cSrcweir 
2069cdf0e10cSrcweir //------------------------------------------------------------------------------
2070cdf0e10cSrcweir void OBoundControlModel::resetField()
2071cdf0e10cSrcweir {
2072cdf0e10cSrcweir     m_xColumnUpdate.clear();
2073cdf0e10cSrcweir     m_xColumn.clear();
2074cdf0e10cSrcweir     m_xField.clear();
2075cdf0e10cSrcweir     m_nFieldType = DataType::OTHER;
2076cdf0e10cSrcweir }
2077cdf0e10cSrcweir 
2078cdf0e10cSrcweir //------------------------------------------------------------------------------
2079cdf0e10cSrcweir sal_Bool OBoundControlModel::connectToField(const Reference<XRowSet>& rForm)
2080cdf0e10cSrcweir {
2081cdf0e10cSrcweir     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::connectToField: invalid call (have an external binding)!" );
2082cdf0e10cSrcweir 
2083cdf0e10cSrcweir 	// wenn eine Verbindung zur Datenbank existiert
2084cdf0e10cSrcweir 	if (rForm.is() && getConnection(rForm).is())
2085cdf0e10cSrcweir 	{
2086cdf0e10cSrcweir 		// Feld bestimmen und PropertyChangeListener
2087cdf0e10cSrcweir 		m_xCursor = rForm;
2088cdf0e10cSrcweir         Reference<XPropertySet> xFieldCandidate;
2089cdf0e10cSrcweir 
2090cdf0e10cSrcweir 		if (m_xCursor.is())
2091cdf0e10cSrcweir 		{
2092cdf0e10cSrcweir             Reference<XColumnsSupplier> xColumnsSupplier(m_xCursor, UNO_QUERY);
2093cdf0e10cSrcweir 			DBG_ASSERT(xColumnsSupplier.is(), "OBoundControlModel::connectToField : the row set should support the com::sun::star::sdb::ResultSet service !");
2094cdf0e10cSrcweir 			if (xColumnsSupplier.is())
2095cdf0e10cSrcweir 			{
2096cdf0e10cSrcweir                 Reference<XNameAccess> xColumns(xColumnsSupplier->getColumns(), UNO_QUERY);
2097cdf0e10cSrcweir 				if (xColumns.is() && xColumns->hasByName(m_aControlSource))
2098cdf0e10cSrcweir 				{
2099cdf0e10cSrcweir 					OSL_VERIFY( xColumns->getByName(m_aControlSource) >>= xFieldCandidate );
2100cdf0e10cSrcweir 				}
2101cdf0e10cSrcweir 			}
2102cdf0e10cSrcweir 		}
2103cdf0e10cSrcweir 
2104cdf0e10cSrcweir         try
2105cdf0e10cSrcweir         {
2106cdf0e10cSrcweir             sal_Int32 nFieldType = DataType::OTHER;
2107cdf0e10cSrcweir 		    if ( xFieldCandidate.is() )
2108cdf0e10cSrcweir 		    {
2109cdf0e10cSrcweir 			    xFieldCandidate->getPropertyValue( PROPERTY_FIELDTYPE ) >>= nFieldType;
2110cdf0e10cSrcweir 			    if ( approveDbColumnType( nFieldType ) )
2111cdf0e10cSrcweir 			        impl_setField_noNotify( xFieldCandidate );
2112cdf0e10cSrcweir             }
2113cdf0e10cSrcweir             else
2114cdf0e10cSrcweir                 impl_setField_noNotify( NULL );
2115cdf0e10cSrcweir 
2116cdf0e10cSrcweir             if ( m_xField.is() )
2117cdf0e10cSrcweir             {
2118cdf0e10cSrcweir 			    if( m_xField->getPropertySetInfo()->hasPropertyByName( PROPERTY_VALUE ) )
2119cdf0e10cSrcweir 			    {
2120cdf0e10cSrcweir                     m_nFieldType = nFieldType;
2121cdf0e10cSrcweir 
2122cdf0e10cSrcweir 				    // an wertaenderungen horchen
2123cdf0e10cSrcweir 				    m_xField->addPropertyChangeListener( PROPERTY_VALUE, this );
2124cdf0e10cSrcweir                     m_xColumnUpdate = Reference< XColumnUpdate >( m_xField, UNO_QUERY );
2125cdf0e10cSrcweir                     m_xColumn = Reference< XColumn >( m_xField, UNO_QUERY );
2126cdf0e10cSrcweir 
2127cdf0e10cSrcweir                     sal_Int32 nNullableFlag = ColumnValue::NO_NULLS;
2128cdf0e10cSrcweir                     m_xField->getPropertyValue(PROPERTY_ISNULLABLE) >>= nNullableFlag;
2129cdf0e10cSrcweir 				    m_bRequired = (ColumnValue::NO_NULLS == nNullableFlag);
2130cdf0e10cSrcweir 					    // we're optimistic : in case of ColumnValue_NULLABLE_UNKNOWN we assume nullability ....
2131cdf0e10cSrcweir 			    }
2132cdf0e10cSrcweir 			    else
2133cdf0e10cSrcweir 			    {
2134cdf0e10cSrcweir 				    OSL_ENSURE(sal_False, "OBoundControlModel::connectToField: property NAME not supported!");
2135cdf0e10cSrcweir 				    impl_setField_noNotify( NULL );
2136cdf0e10cSrcweir 			    }
2137cdf0e10cSrcweir             }
2138cdf0e10cSrcweir         }
2139cdf0e10cSrcweir         catch( const Exception& )
2140cdf0e10cSrcweir         {
2141cdf0e10cSrcweir         	DBG_UNHANDLED_EXCEPTION();
2142cdf0e10cSrcweir             resetField();
2143cdf0e10cSrcweir         }
2144cdf0e10cSrcweir 	}
2145cdf0e10cSrcweir 	return hasField();
2146cdf0e10cSrcweir }
2147cdf0e10cSrcweir 
2148cdf0e10cSrcweir //------------------------------------------------------------------------------
2149cdf0e10cSrcweir void OBoundControlModel::initFromField( const Reference< XRowSet >& _rxRowSet )
2150cdf0e10cSrcweir {
2151cdf0e10cSrcweir 	// but only if the rowset if posisitioned on a valid record
2152cdf0e10cSrcweir 	if ( hasField() && _rxRowSet.is() )
2153cdf0e10cSrcweir 	{
2154cdf0e10cSrcweir 		if ( !_rxRowSet->isBeforeFirst() && !_rxRowSet->isAfterLast() )
2155cdf0e10cSrcweir 			transferDbValueToControl();
2156cdf0e10cSrcweir         else
2157cdf0e10cSrcweir             // reset the field if the row set is empty
2158cdf0e10cSrcweir             // #i30661# / 2004-12-16 / frank.schoenheit@sun.com
2159cdf0e10cSrcweir             resetNoBroadcast();
2160cdf0e10cSrcweir 	}
2161cdf0e10cSrcweir }
2162cdf0e10cSrcweir 
2163cdf0e10cSrcweir //------------------------------------------------------------------------------
2164cdf0e10cSrcweir sal_Bool OBoundControlModel::approveDbColumnType(sal_Int32 _nColumnType)
2165cdf0e10cSrcweir {
2166cdf0e10cSrcweir     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::approveDbColumnType: invalid call (have an external binding)!" );
2167cdf0e10cSrcweir 
2168cdf0e10cSrcweir     if ((_nColumnType == DataType::BINARY) || (_nColumnType == DataType::VARBINARY)
2169cdf0e10cSrcweir 		|| (_nColumnType == DataType::LONGVARBINARY) || (_nColumnType == DataType::OTHER)
2170cdf0e10cSrcweir 		|| (_nColumnType == DataType::OBJECT) || (_nColumnType == DataType::DISTINCT)
2171cdf0e10cSrcweir 		|| (_nColumnType == DataType::STRUCT) || (_nColumnType == DataType::ARRAY)
2172cdf0e10cSrcweir 		|| (_nColumnType == DataType::BLOB) /*|| (_nColumnType == DataType::CLOB)*/
2173cdf0e10cSrcweir 		|| (_nColumnType == DataType::REF) || (_nColumnType == DataType::SQLNULL))
2174cdf0e10cSrcweir 		return sal_False;
2175cdf0e10cSrcweir 
2176cdf0e10cSrcweir 	return sal_True;
2177cdf0e10cSrcweir }
2178cdf0e10cSrcweir 
2179cdf0e10cSrcweir //------------------------------------------------------------------------------
2180cdf0e10cSrcweir void OBoundControlModel::impl_determineAmbientForm_nothrow()
2181cdf0e10cSrcweir {
2182cdf0e10cSrcweir     Reference< XInterface > xParent( const_cast< OBoundControlModel* >( this )->getParent() );
2183cdf0e10cSrcweir 
2184cdf0e10cSrcweir     m_xAmbientForm.set( xParent, UNO_QUERY );
2185cdf0e10cSrcweir     if ( !m_xAmbientForm.is() )
2186cdf0e10cSrcweir     {
2187cdf0e10cSrcweir         Reference< XRowSetSupplier > xSupRowSet( xParent, UNO_QUERY );
2188cdf0e10cSrcweir         if ( xSupRowSet.is() )
2189cdf0e10cSrcweir             m_xAmbientForm.set( xSupRowSet->getRowSet(), UNO_QUERY );
2190cdf0e10cSrcweir     }
2191cdf0e10cSrcweir }
2192cdf0e10cSrcweir 
2193cdf0e10cSrcweir //------------------------------------------------------------------------------
2194cdf0e10cSrcweir void OBoundControlModel::impl_connectDatabaseColumn_noNotify( bool _bFromReload )
2195cdf0e10cSrcweir {
2196cdf0e10cSrcweir     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::impl_connectDatabaseColumn_noNotify: not to be called with an external value binding!" );
2197cdf0e10cSrcweir 
2198cdf0e10cSrcweir     // consistency checks
2199cdf0e10cSrcweir     DBG_ASSERT( !( hasField() && !_bFromReload ),
2200cdf0e10cSrcweir         "OBoundControlModel::impl_connectDatabaseColumn_noNotify: the form is just *loaded*, but we already have a field!" );
2201cdf0e10cSrcweir     (void)_bFromReload;
2202cdf0e10cSrcweir 
2203cdf0e10cSrcweir     Reference< XRowSet > xRowSet( m_xAmbientForm, UNO_QUERY );
2204cdf0e10cSrcweir     OSL_ENSURE( xRowSet.is(), "OBoundControlModel::impl_connectDatabaseColumn_noNotify: no row set!" );
2205cdf0e10cSrcweir     if ( !xRowSet.is() )
2206cdf0e10cSrcweir         return;
2207cdf0e10cSrcweir 
2208cdf0e10cSrcweir 	if ( !hasField() )
2209cdf0e10cSrcweir 	{
2210cdf0e10cSrcweir         // connect to the column
2211cdf0e10cSrcweir 	    connectToField( xRowSet );
2212cdf0e10cSrcweir     }
2213cdf0e10cSrcweir 
2214cdf0e10cSrcweir     // now that we're connected (more or less, even if we did not find a column),
2215cdf0e10cSrcweir     // we definately want to forward any potentially occuring value changes
2216cdf0e10cSrcweir     m_bForwardValueChanges = sal_True;
2217cdf0e10cSrcweir 
2218cdf0e10cSrcweir     // let derived classes react on this new connection
2219cdf0e10cSrcweir 	m_bLoaded = sal_True;
2220cdf0e10cSrcweir 	onConnectedDbColumn( xRowSet );
2221cdf0e10cSrcweir 
2222cdf0e10cSrcweir     // initially transfer the db column value to the control, if we successfully connected to a database column
2223cdf0e10cSrcweir 	if ( hasField() )
2224cdf0e10cSrcweir         initFromField( xRowSet );
2225cdf0e10cSrcweir }
2226cdf0e10cSrcweir 
2227cdf0e10cSrcweir //------------------------------------------------------------------------------
2228cdf0e10cSrcweir void OBoundControlModel::impl_disconnectDatabaseColumn_noNotify()
2229cdf0e10cSrcweir {
2230cdf0e10cSrcweir     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::impl_disconnectDatabaseColumn_noNotify: not to be called with an external value binding!" );
2231cdf0e10cSrcweir 
2232cdf0e10cSrcweir     // let derived classes react on this
2233cdf0e10cSrcweir     onDisconnectedDbColumn();
2234cdf0e10cSrcweir 
2235cdf0e10cSrcweir 	if ( hasField() )
2236cdf0e10cSrcweir 	{
2237cdf0e10cSrcweir 		getField()->removePropertyChangeListener( PROPERTY_VALUE, this );
2238cdf0e10cSrcweir 		resetField();
2239cdf0e10cSrcweir 	}
2240cdf0e10cSrcweir 
2241cdf0e10cSrcweir     m_xCursor = NULL;
2242cdf0e10cSrcweir 	m_bLoaded = sal_False;
2243cdf0e10cSrcweir }
2244cdf0e10cSrcweir 
2245cdf0e10cSrcweir //==============================================================================
2246cdf0e10cSrcweir // XLoadListener
2247cdf0e10cSrcweir //------------------------------------------------------------------------------
2248cdf0e10cSrcweir void SAL_CALL OBoundControlModel::loaded( const EventObject& _rEvent ) throw(RuntimeException)
2249cdf0e10cSrcweir {
2250cdf0e10cSrcweir     ControlModelLock aLock( *this );
2251cdf0e10cSrcweir     FieldChangeNotifier aBoundFieldNotifier( aLock );
2252cdf0e10cSrcweir 
2253cdf0e10cSrcweir     OSL_ENSURE( _rEvent.Source == m_xAmbientForm, "OBoundControlModel::loaded: where does this come from?" );
2254cdf0e10cSrcweir     (void)_rEvent;
2255cdf0e10cSrcweir 
2256cdf0e10cSrcweir     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::loaded: we should never reach this with an external value binding!" );
2257cdf0e10cSrcweir     if ( hasExternalValueBinding() )
2258cdf0e10cSrcweir         return;
2259cdf0e10cSrcweir 
2260cdf0e10cSrcweir     impl_connectDatabaseColumn_noNotify( false );
2261cdf0e10cSrcweir }
2262cdf0e10cSrcweir 
2263cdf0e10cSrcweir 
2264cdf0e10cSrcweir //------------------------------------------------------------------------------
2265cdf0e10cSrcweir void SAL_CALL OBoundControlModel::unloaded( const com::sun::star::lang::EventObject& /*aEvent*/ ) throw(RuntimeException)
2266cdf0e10cSrcweir {
2267cdf0e10cSrcweir     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::unloaded: we should never reach this with an external value binding!" );
2268cdf0e10cSrcweir }
2269cdf0e10cSrcweir 
2270cdf0e10cSrcweir //------------------------------------------------------------------------------
2271cdf0e10cSrcweir void SAL_CALL OBoundControlModel::reloading( const com::sun::star::lang::EventObject& /*aEvent*/ ) throw(RuntimeException)
2272cdf0e10cSrcweir {
2273cdf0e10cSrcweir     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::reloading: we should never reach this with an external value binding!" );
2274cdf0e10cSrcweir     if ( hasExternalValueBinding() )
2275cdf0e10cSrcweir         return;
2276cdf0e10cSrcweir 
2277cdf0e10cSrcweir 	osl::MutexGuard aGuard(m_aMutex);
2278cdf0e10cSrcweir 	m_bForwardValueChanges = sal_False;
2279cdf0e10cSrcweir }
2280cdf0e10cSrcweir 
2281cdf0e10cSrcweir //------------------------------------------------------------------------------
2282cdf0e10cSrcweir void SAL_CALL OBoundControlModel::unloading(const com::sun::star::lang::EventObject& /*aEvent*/) throw(RuntimeException)
2283cdf0e10cSrcweir {
2284cdf0e10cSrcweir     ControlModelLock aLock( *this );
2285cdf0e10cSrcweir     FieldChangeNotifier aBoundFieldNotifier( aLock );
2286cdf0e10cSrcweir 
2287cdf0e10cSrcweir     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::unloading: we should never reach this with an external value binding!" );
2288cdf0e10cSrcweir     if ( hasExternalValueBinding() )
2289cdf0e10cSrcweir         return;
2290cdf0e10cSrcweir 
2291cdf0e10cSrcweir     impl_disconnectDatabaseColumn_noNotify();
2292cdf0e10cSrcweir }
2293cdf0e10cSrcweir 
2294cdf0e10cSrcweir //------------------------------------------------------------------------------
2295cdf0e10cSrcweir void SAL_CALL OBoundControlModel::reloaded( const EventObject& _rEvent ) throw(RuntimeException)
2296cdf0e10cSrcweir {
2297cdf0e10cSrcweir     ControlModelLock aLock( *this );
2298cdf0e10cSrcweir     FieldChangeNotifier aBoundFieldNotifier( aLock );
2299cdf0e10cSrcweir 
2300cdf0e10cSrcweir     OSL_ENSURE( _rEvent.Source == m_xAmbientForm, "OBoundControlModel::reloaded: where does this come from?" );
2301cdf0e10cSrcweir     (void)_rEvent;
2302cdf0e10cSrcweir 
2303cdf0e10cSrcweir     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::reloaded: we should never reach this with an external value binding!" );
2304cdf0e10cSrcweir     if ( hasExternalValueBinding() )
2305cdf0e10cSrcweir         return;
2306cdf0e10cSrcweir 
2307cdf0e10cSrcweir     impl_connectDatabaseColumn_noNotify( true );
2308cdf0e10cSrcweir }
2309cdf0e10cSrcweir 
2310cdf0e10cSrcweir //------------------------------------------------------------------------------
2311cdf0e10cSrcweir void OBoundControlModel::setControlValue( const Any& _rValue, ValueChangeInstigator _eInstigator )
2312cdf0e10cSrcweir {
2313cdf0e10cSrcweir 	m_eControlValueChangeInstigator = _eInstigator;
2314cdf0e10cSrcweir     doSetControlValue( _rValue );
2315cdf0e10cSrcweir 	m_eControlValueChangeInstigator = eOther;
2316cdf0e10cSrcweir }
2317cdf0e10cSrcweir 
2318cdf0e10cSrcweir //------------------------------------------------------------------------------
2319cdf0e10cSrcweir void OBoundControlModel::doSetControlValue( const Any& _rValue )
2320cdf0e10cSrcweir {
2321cdf0e10cSrcweir 	OSL_PRECOND( m_xAggregateFastSet.is() && m_xAggregateSet.is(),
2322cdf0e10cSrcweir         "OBoundControlModel::doSetControlValue: invalid aggregate !" );
2323cdf0e10cSrcweir     OSL_PRECOND( m_sValuePropertyName.getLength() || ( m_nValuePropertyAggregateHandle != -1 ),
2324cdf0e10cSrcweir         "OBoundControlModel::doSetControlValue: please override if you have own value property handling!" );
2325cdf0e10cSrcweir 
2326cdf0e10cSrcweir     try
2327cdf0e10cSrcweir     {
2328cdf0e10cSrcweir         // release our mutex once (it's acquired in one of the the calling methods), as setting aggregate properties
2329cdf0e10cSrcweir 	    // may cause any uno controls belonging to us to lock the solar mutex, which is potentially dangerous with
2330cdf0e10cSrcweir 	    // our own mutex locked
2331cdf0e10cSrcweir 	    // #72451# / 2000-01-31 / frank.schoenheit@sun.com
2332cdf0e10cSrcweir         MutexRelease aRelease( m_aMutex );
2333cdf0e10cSrcweir         if ( ( m_nValuePropertyAggregateHandle != -1 ) && m_xAggregateFastSet.is() )
2334cdf0e10cSrcweir         {
2335cdf0e10cSrcweir             m_xAggregateFastSet->setFastPropertyValue( m_nValuePropertyAggregateHandle, _rValue );
2336cdf0e10cSrcweir         }
2337cdf0e10cSrcweir         else if ( m_sValuePropertyName.getLength() && m_xAggregateSet.is() )
2338cdf0e10cSrcweir         {
2339cdf0e10cSrcweir             m_xAggregateSet->setPropertyValue( m_sValuePropertyName, _rValue );
2340cdf0e10cSrcweir         }
2341cdf0e10cSrcweir     }
2342cdf0e10cSrcweir     catch( const Exception& )
2343cdf0e10cSrcweir     {
2344cdf0e10cSrcweir     	OSL_ENSURE( sal_False, "OBoundControlModel::doSetControlValue: caught an exception!" );
2345cdf0e10cSrcweir     }
2346cdf0e10cSrcweir }
2347cdf0e10cSrcweir 
2348cdf0e10cSrcweir //------------------------------------------------------------------------------
2349cdf0e10cSrcweir void OBoundControlModel::onConnectedValidator( )
2350cdf0e10cSrcweir {
2351cdf0e10cSrcweir     try
2352cdf0e10cSrcweir     {
2353cdf0e10cSrcweir         // if we have an external validator, we do not want the control to force invalid
2354cdf0e10cSrcweir         // inputs to the default value. Instead, invalid inputs should be translated
2355cdf0e10cSrcweir         // to NaN (not a number)
2356cdf0e10cSrcweir         Reference< XPropertySetInfo > xAggregatePropertyInfo;
2357cdf0e10cSrcweir         if ( m_xAggregateSet.is() )
2358cdf0e10cSrcweir             xAggregatePropertyInfo = m_xAggregateSet->getPropertySetInfo();
2359cdf0e10cSrcweir         if ( xAggregatePropertyInfo.is() && xAggregatePropertyInfo->hasPropertyByName( PROPERTY_ENFORCE_FORMAT ) )
2360cdf0e10cSrcweir             m_xAggregateSet->setPropertyValue( PROPERTY_ENFORCE_FORMAT, makeAny( (sal_Bool)sal_False ) );
2361cdf0e10cSrcweir     }
2362cdf0e10cSrcweir     catch( const Exception& )
2363cdf0e10cSrcweir     {
2364cdf0e10cSrcweir     	OSL_ENSURE( sal_False, "OBoundControlModel::onConnectedValidator: caught an exception!" );
2365cdf0e10cSrcweir     }
2366cdf0e10cSrcweir     recheckValidity( false );
2367cdf0e10cSrcweir }
2368cdf0e10cSrcweir 
2369cdf0e10cSrcweir //------------------------------------------------------------------------------
2370cdf0e10cSrcweir void OBoundControlModel::onDisconnectedValidator( )
2371cdf0e10cSrcweir {
2372cdf0e10cSrcweir     try
2373cdf0e10cSrcweir     {
2374cdf0e10cSrcweir         Reference< XPropertySetInfo > xAggregatePropertyInfo;
2375cdf0e10cSrcweir         if ( m_xAggregateSet.is() )
2376cdf0e10cSrcweir             xAggregatePropertyInfo = m_xAggregateSet->getPropertySetInfo();
2377cdf0e10cSrcweir         if ( xAggregatePropertyInfo.is() && xAggregatePropertyInfo->hasPropertyByName( PROPERTY_ENFORCE_FORMAT ) )
2378cdf0e10cSrcweir             m_xAggregateSet->setPropertyValue( PROPERTY_ENFORCE_FORMAT, makeAny( (sal_Bool)sal_True ) );
2379cdf0e10cSrcweir     }
2380cdf0e10cSrcweir     catch( const Exception& )
2381cdf0e10cSrcweir     {
2382cdf0e10cSrcweir     	OSL_ENSURE( sal_False, "OBoundControlModel::onDisconnectedValidator: caught an exception!" );
2383cdf0e10cSrcweir     }
2384cdf0e10cSrcweir     recheckValidity( false );
2385cdf0e10cSrcweir }
2386cdf0e10cSrcweir 
2387cdf0e10cSrcweir //------------------------------------------------------------------------------
2388cdf0e10cSrcweir void OBoundControlModel::onConnectedExternalValue( )
2389cdf0e10cSrcweir {
2390cdf0e10cSrcweir     calculateExternalValueType();
2391cdf0e10cSrcweir }
2392cdf0e10cSrcweir 
2393cdf0e10cSrcweir //------------------------------------------------------------------------------
2394cdf0e10cSrcweir void OBoundControlModel::onDisconnectedExternalValue( )
2395cdf0e10cSrcweir {
2396cdf0e10cSrcweir }
2397cdf0e10cSrcweir 
2398cdf0e10cSrcweir //------------------------------------------------------------------------------
2399cdf0e10cSrcweir void OBoundControlModel::onConnectedDbColumn( const Reference< XInterface >& /*_rxForm*/ )
2400cdf0e10cSrcweir {
2401cdf0e10cSrcweir     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::onConnectedDbColumn: how this? There's an external value binding!" );
2402cdf0e10cSrcweir }
2403cdf0e10cSrcweir 
2404cdf0e10cSrcweir //------------------------------------------------------------------------------
2405cdf0e10cSrcweir void OBoundControlModel::onDisconnectedDbColumn()
2406cdf0e10cSrcweir {
2407cdf0e10cSrcweir     OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::onDisconnectedDbColumn: how this? There's an external value binding!" );
2408cdf0e10cSrcweir }
2409cdf0e10cSrcweir 
2410cdf0e10cSrcweir // XReset
2411cdf0e10cSrcweir //-----------------------------------------------------------------------------
2412cdf0e10cSrcweir Any OBoundControlModel::getDefaultForReset() const
2413cdf0e10cSrcweir {
2414cdf0e10cSrcweir     return Any();
2415cdf0e10cSrcweir }
2416cdf0e10cSrcweir 
2417cdf0e10cSrcweir //-----------------------------------------------------------------------------
2418cdf0e10cSrcweir void OBoundControlModel::resetNoBroadcast()
2419cdf0e10cSrcweir {
2420cdf0e10cSrcweir     setControlValue( getDefaultForReset(), eOther );
2421cdf0e10cSrcweir }
2422cdf0e10cSrcweir 
2423cdf0e10cSrcweir //-----------------------------------------------------------------------------
2424cdf0e10cSrcweir void OBoundControlModel::addResetListener(const Reference<XResetListener>& l) throw (RuntimeException)
2425cdf0e10cSrcweir {
2426cdf0e10cSrcweir     m_aResetHelper.addResetListener( l );
2427cdf0e10cSrcweir }
2428cdf0e10cSrcweir 
2429cdf0e10cSrcweir //-----------------------------------------------------------------------------
2430cdf0e10cSrcweir void OBoundControlModel::removeResetListener(const Reference<XResetListener>& l) throw (RuntimeException)
2431cdf0e10cSrcweir {
2432cdf0e10cSrcweir     m_aResetHelper.removeResetListener( l );
2433cdf0e10cSrcweir }
2434cdf0e10cSrcweir 
2435cdf0e10cSrcweir //-----------------------------------------------------------------------------
2436cdf0e10cSrcweir void OBoundControlModel::reset() throw (RuntimeException)
2437cdf0e10cSrcweir {
2438cdf0e10cSrcweir     if ( !m_aResetHelper.approveReset() )
2439cdf0e10cSrcweir        return;
2440cdf0e10cSrcweir 
2441cdf0e10cSrcweir     ControlModelLock aLock( *this );
2442cdf0e10cSrcweir 
2443cdf0e10cSrcweir     // on a new record?
2444cdf0e10cSrcweir     sal_Bool bIsNewRecord = sal_False;
2445cdf0e10cSrcweir 	Reference<XPropertySet> xSet( m_xCursor, UNO_QUERY );
2446cdf0e10cSrcweir     if ( xSet.is() )
2447cdf0e10cSrcweir     {
2448cdf0e10cSrcweir         try
2449cdf0e10cSrcweir         {
2450cdf0e10cSrcweir 		    xSet->getPropertyValue( PROPERTY_ISNEW ) >>= bIsNewRecord;
2451cdf0e10cSrcweir         }
2452cdf0e10cSrcweir         catch( const Exception& )
2453cdf0e10cSrcweir         {
2454cdf0e10cSrcweir             DBG_UNHANDLED_EXCEPTION();
2455cdf0e10cSrcweir         }
2456cdf0e10cSrcweir     }
2457cdf0e10cSrcweir 
2458cdf0e10cSrcweir     // cursor on an invalid row?
2459cdf0e10cSrcweir     sal_Bool bInvalidCursorPosition = sal_True;
2460cdf0e10cSrcweir     try
2461cdf0e10cSrcweir     {
2462cdf0e10cSrcweir         bInvalidCursorPosition =    m_xCursor.is()
2463cdf0e10cSrcweir                                 &&  (  m_xCursor->isAfterLast()
2464cdf0e10cSrcweir                                     || m_xCursor->isBeforeFirst()
2465cdf0e10cSrcweir                                     )
2466cdf0e10cSrcweir                                 &&  !bIsNewRecord;
2467cdf0e10cSrcweir     }
2468cdf0e10cSrcweir     catch( const SQLException& )
2469cdf0e10cSrcweir     {
2470cdf0e10cSrcweir         OSL_ENSURE( sal_False, "OBoundControlModel::reset: caught an SQL exception!" );
2471cdf0e10cSrcweir     }
2472cdf0e10cSrcweir     // don't count the insert row as "invalid"
2473cdf0e10cSrcweir     // @since  #i24495#
2474cdf0e10cSrcweir     // @date   2004-05-14
2475cdf0e10cSrcweir     // @author fs@openoffice.org
2476cdf0e10cSrcweir 
2477cdf0e10cSrcweir 	sal_Bool bSimpleReset =
2478cdf0e10cSrcweir                         (   !m_xColumn.is()						// no connection to a database column
2479cdf0e10cSrcweir 						||	(	m_xCursor.is()					// OR	we have an improperly positioned cursor
2480cdf0e10cSrcweir 							&&	bInvalidCursorPosition
2481cdf0e10cSrcweir 							)
2482cdf0e10cSrcweir                         ||  hasExternalValueBinding()           // OR we have an external value binding
2483cdf0e10cSrcweir                         );
2484cdf0e10cSrcweir 
2485cdf0e10cSrcweir 	if ( !bSimpleReset )
2486cdf0e10cSrcweir 	{
2487cdf0e10cSrcweir 		// The default values will be set if and only if the current value of the field which we're bound
2488cdf0e10cSrcweir 		// to is NULL.
2489cdf0e10cSrcweir 		// Else, the current field value should be refreshed
2490cdf0e10cSrcweir 		// This behaviour is not completely ... "matured": What should happen if the field as well as the
2491cdf0e10cSrcweir 		// control have a default value?
2492cdf0e10cSrcweir 
2493cdf0e10cSrcweir 		sal_Bool bIsNull = sal_True;
2494cdf0e10cSrcweir 		// we have to access the field content at least once to get a reliable result by XColumn::wasNull
2495cdf0e10cSrcweir 		try
2496cdf0e10cSrcweir 		{
2497cdf0e10cSrcweir             // normally, we'd do a getString here. However, this is extremely expensive in the case
2498cdf0e10cSrcweir             // of binary fields. Unfortunately, getString is the only method which is guaranteed
2499cdf0e10cSrcweir             // to *always* succeed, all other getXXX methods may fail if the column is asked for a
2500cdf0e10cSrcweir             // non-convertible type
2501cdf0e10cSrcweir             sal_Int32 nFieldType = DataType::OBJECT;
2502cdf0e10cSrcweir             getField()->getPropertyValue( PROPERTY_FIELDTYPE ) >>= nFieldType;
2503cdf0e10cSrcweir             if  (  ( nFieldType == DataType::BINARY        )
2504cdf0e10cSrcweir                 || ( nFieldType == DataType::VARBINARY     )
2505cdf0e10cSrcweir                 || ( nFieldType == DataType::LONGVARBINARY )
2506cdf0e10cSrcweir                 || ( nFieldType == DataType::OBJECT        )
2507cdf0e10cSrcweir                 /*|| ( nFieldType == DataType::CLOB          )*/
2508cdf0e10cSrcweir                 )
2509cdf0e10cSrcweir                 m_xColumn->getBinaryStream();
2510cdf0e10cSrcweir             else if ( nFieldType == DataType::BLOB          )
2511cdf0e10cSrcweir                 m_xColumn->getBlob();
2512cdf0e10cSrcweir             else
2513cdf0e10cSrcweir                 m_xColumn->getString();
2514cdf0e10cSrcweir 
2515cdf0e10cSrcweir             bIsNull = m_xColumn->wasNull();
2516cdf0e10cSrcweir 		}
2517cdf0e10cSrcweir 		catch(Exception&)
2518cdf0e10cSrcweir 		{
2519cdf0e10cSrcweir 			DBG_ERROR("OBoundControlModel::reset: this should have succeeded in all cases!");
2520cdf0e10cSrcweir 		}
2521cdf0e10cSrcweir 
2522cdf0e10cSrcweir         sal_Bool bNeedValueTransfer = sal_True;
2523cdf0e10cSrcweir 
2524cdf0e10cSrcweir 		if ( bIsNull )
2525cdf0e10cSrcweir 		{
2526cdf0e10cSrcweir             if ( bIsNewRecord )
2527cdf0e10cSrcweir 			{
2528cdf0e10cSrcweir                 // reset the control to it's default
2529cdf0e10cSrcweir 				resetNoBroadcast();
2530cdf0e10cSrcweir                 // and immediately commit the changes to the DB column, to keep consistency
2531cdf0e10cSrcweir                 commitControlValueToDbColumn( sal_True );
2532cdf0e10cSrcweir 
2533cdf0e10cSrcweir                 bNeedValueTransfer = sal_False;
2534cdf0e10cSrcweir 			}
2535cdf0e10cSrcweir 		}
2536cdf0e10cSrcweir 
2537cdf0e10cSrcweir         if ( bNeedValueTransfer )
2538cdf0e10cSrcweir 			transferDbValueToControl();
2539cdf0e10cSrcweir 	}
2540cdf0e10cSrcweir 	else
2541cdf0e10cSrcweir     {
2542cdf0e10cSrcweir 		resetNoBroadcast();
2543cdf0e10cSrcweir 
2544cdf0e10cSrcweir         // transfer to the external binding, if necessary
2545cdf0e10cSrcweir         if ( hasExternalValueBinding() )
2546cdf0e10cSrcweir             transferControlValueToExternal( aLock );
2547cdf0e10cSrcweir     }
2548cdf0e10cSrcweir 
2549cdf0e10cSrcweir     // revalidate, if necessary
2550cdf0e10cSrcweir     if ( hasValidator() )
2551cdf0e10cSrcweir         recheckValidity( true );
2552cdf0e10cSrcweir 
2553cdf0e10cSrcweir     aLock.release();
2554cdf0e10cSrcweir 
2555cdf0e10cSrcweir     m_aResetHelper.notifyResetted();
2556cdf0e10cSrcweir }
2557cdf0e10cSrcweir 
2558cdf0e10cSrcweir // -----------------------------------------------------------------------------
2559cdf0e10cSrcweir void OBoundControlModel::impl_setField_noNotify( const Reference< XPropertySet>& _rxField )
2560cdf0e10cSrcweir {
2561cdf0e10cSrcweir     DBG_ASSERT( !hasExternalValueBinding(), "OBoundControlModel::impl_setField_noNotify: We have an external value binding!" );
2562cdf0e10cSrcweir 	m_xField = _rxField;
2563cdf0e10cSrcweir }
2564cdf0e10cSrcweir 
2565cdf0e10cSrcweir //--------------------------------------------------------------------
2566cdf0e10cSrcweir sal_Bool OBoundControlModel::impl_approveValueBinding_nolock( const Reference< XValueBinding >& _rxBinding )
2567cdf0e10cSrcweir {
2568cdf0e10cSrcweir     if ( !_rxBinding.is() )
2569cdf0e10cSrcweir         return sal_False;
2570cdf0e10cSrcweir 
2571cdf0e10cSrcweir     Sequence< Type > aTypeCandidates;
2572cdf0e10cSrcweir     {
2573cdf0e10cSrcweir         // SYNCHRONIZED -->
2574cdf0e10cSrcweir         ::osl::MutexGuard aGuard( m_aMutex );
2575cdf0e10cSrcweir         aTypeCandidates = getSupportedBindingTypes();
2576cdf0e10cSrcweir         // <-- SYNCHRONIZED
2577cdf0e10cSrcweir     }
2578cdf0e10cSrcweir 
2579cdf0e10cSrcweir     for (   const Type* pType = aTypeCandidates.getConstArray();
2580cdf0e10cSrcweir             pType != aTypeCandidates.getConstArray() + aTypeCandidates.getLength();
2581cdf0e10cSrcweir             ++pType
2582cdf0e10cSrcweir         )
2583cdf0e10cSrcweir     {
2584cdf0e10cSrcweir         if ( _rxBinding->supportsType( *pType ) )
2585cdf0e10cSrcweir             return sal_True;
2586cdf0e10cSrcweir     }
2587cdf0e10cSrcweir 
2588cdf0e10cSrcweir     return sal_False;
2589cdf0e10cSrcweir }
2590cdf0e10cSrcweir 
2591cdf0e10cSrcweir //--------------------------------------------------------------------
2592cdf0e10cSrcweir void OBoundControlModel::connectExternalValueBinding(
2593cdf0e10cSrcweir         const Reference< XValueBinding >& _rxBinding, ControlModelLock& _rInstanceLock )
2594cdf0e10cSrcweir {
2595cdf0e10cSrcweir     OSL_PRECOND( _rxBinding.is(), "OBoundControlModel::connectExternalValueBinding: invalid binding instance!" );
2596cdf0e10cSrcweir     OSL_PRECOND( !hasExternalValueBinding( ), "OBoundControlModel::connectExternalValueBinding: precond not met (currently have a binding)!" );
2597cdf0e10cSrcweir 
2598cdf0e10cSrcweir     // if we're connected to a database column, suspend this
2599cdf0e10cSrcweir     if ( hasField() )
2600cdf0e10cSrcweir         impl_disconnectDatabaseColumn_noNotify();
2601cdf0e10cSrcweir 
2602cdf0e10cSrcweir     // suspend listening for load-related events at out ambient form.
2603cdf0e10cSrcweir     // This is because an external value binding overrules a possible database binding.
2604cdf0e10cSrcweir     if ( isFormListening() )
2605cdf0e10cSrcweir         doFormListening( false );
2606cdf0e10cSrcweir 
2607cdf0e10cSrcweir     // remember this new binding
2608cdf0e10cSrcweir     m_xExternalBinding = _rxBinding;
2609cdf0e10cSrcweir 
2610cdf0e10cSrcweir     // tell the derivee
2611cdf0e10cSrcweir     onConnectedExternalValue();
2612cdf0e10cSrcweir 
2613cdf0e10cSrcweir     try
2614cdf0e10cSrcweir     {
2615cdf0e10cSrcweir         // add as value listener so we get notified when the value changes
2616cdf0e10cSrcweir         Reference< XModifyBroadcaster > xModifiable( m_xExternalBinding, UNO_QUERY );
2617cdf0e10cSrcweir         if ( xModifiable.is() )
2618cdf0e10cSrcweir             xModifiable->addModifyListener( this );
2619cdf0e10cSrcweir 
2620cdf0e10cSrcweir         // add as property change listener for some (possibly present) properties we're
2621cdf0e10cSrcweir         // interested in
2622cdf0e10cSrcweir         Reference< XPropertySet > xBindingProps( m_xExternalBinding, UNO_QUERY );
2623cdf0e10cSrcweir         Reference< XPropertySetInfo > xBindingPropsInfo( xBindingProps.is() ? xBindingProps->getPropertySetInfo() : Reference< XPropertySetInfo >() );
2624cdf0e10cSrcweir         if ( xBindingPropsInfo.is() )
2625cdf0e10cSrcweir         {
2626cdf0e10cSrcweir             if ( xBindingPropsInfo->hasPropertyByName( PROPERTY_READONLY ) )
2627cdf0e10cSrcweir             {
2628cdf0e10cSrcweir                 xBindingProps->addPropertyChangeListener( PROPERTY_READONLY, this );
2629cdf0e10cSrcweir                 m_bBindingControlsRO = sal_True;
2630cdf0e10cSrcweir             }
2631cdf0e10cSrcweir             if ( xBindingPropsInfo->hasPropertyByName( PROPERTY_RELEVANT ) )
2632cdf0e10cSrcweir             {
2633cdf0e10cSrcweir                 xBindingProps->addPropertyChangeListener( PROPERTY_RELEVANT, this );
2634cdf0e10cSrcweir                 m_bBindingControlsEnable = sal_True;
2635cdf0e10cSrcweir             }
2636cdf0e10cSrcweir         }
2637cdf0e10cSrcweir     }
2638cdf0e10cSrcweir     catch( const Exception& )
2639cdf0e10cSrcweir     {
2640cdf0e10cSrcweir         DBG_UNHANDLED_EXCEPTION();
2641cdf0e10cSrcweir     }
2642cdf0e10cSrcweir 
2643cdf0e10cSrcweir     // propagate our new value
2644cdf0e10cSrcweir     transferExternalValueToControl( _rInstanceLock );
2645cdf0e10cSrcweir 
2646cdf0e10cSrcweir     // if the binding is also a validator, use it, too. This is a constraint of the
2647cdf0e10cSrcweir     // com.sun.star.form.binding.ValidatableBindableFormComponent service
2648cdf0e10cSrcweir     if ( m_bSupportsValidation )
2649cdf0e10cSrcweir     {
2650cdf0e10cSrcweir         try
2651cdf0e10cSrcweir         {
2652cdf0e10cSrcweir             Reference< XValidator > xAsValidator( _rxBinding, UNO_QUERY );
2653cdf0e10cSrcweir             if ( xAsValidator.is() )
2654cdf0e10cSrcweir                 setValidator( xAsValidator );
2655cdf0e10cSrcweir         }
2656cdf0e10cSrcweir         catch( const Exception& )
2657cdf0e10cSrcweir         {
2658cdf0e10cSrcweir             DBG_UNHANDLED_EXCEPTION();
2659cdf0e10cSrcweir         }
2660cdf0e10cSrcweir     }
2661cdf0e10cSrcweir }
2662cdf0e10cSrcweir 
2663cdf0e10cSrcweir //--------------------------------------------------------------------
2664cdf0e10cSrcweir void OBoundControlModel::disconnectExternalValueBinding( )
2665cdf0e10cSrcweir {
2666cdf0e10cSrcweir     try
2667cdf0e10cSrcweir     {
2668cdf0e10cSrcweir         // not listening at the binding anymore
2669cdf0e10cSrcweir         Reference< XModifyBroadcaster > xModifiable( m_xExternalBinding, UNO_QUERY );
2670cdf0e10cSrcweir         if ( xModifiable.is() )
2671cdf0e10cSrcweir             xModifiable->removeModifyListener( this );
2672cdf0e10cSrcweir 
2673cdf0e10cSrcweir         // remove as property change listener
2674cdf0e10cSrcweir         Reference< XPropertySet > xBindingProps( m_xExternalBinding, UNO_QUERY );
2675cdf0e10cSrcweir         if ( m_bBindingControlsRO )
2676cdf0e10cSrcweir             xBindingProps->removePropertyChangeListener( PROPERTY_READONLY, this );
2677cdf0e10cSrcweir         if ( m_bBindingControlsEnable )
2678cdf0e10cSrcweir             xBindingProps->removePropertyChangeListener( PROPERTY_RELEVANT, this );
2679cdf0e10cSrcweir     }
2680cdf0e10cSrcweir     catch( const Exception& )
2681cdf0e10cSrcweir     {
2682cdf0e10cSrcweir     	OSL_ENSURE( sal_False, "OBoundControlModel::disconnectExternalValueBinding: caught an exception!" );
2683cdf0e10cSrcweir     }
2684cdf0e10cSrcweir 
2685cdf0e10cSrcweir     // if the binding also acts as our validator, disconnect the validator, too
2686cdf0e10cSrcweir     if ( ( m_xExternalBinding == m_xValidator ) && m_xValidator.is() )
2687cdf0e10cSrcweir         disconnectValidator( );
2688cdf0e10cSrcweir 
2689cdf0e10cSrcweir     // no binding anymore
2690cdf0e10cSrcweir     m_xExternalBinding.clear();
2691cdf0e10cSrcweir 
2692cdf0e10cSrcweir     // be a load listener at our form, again. This was suspended while we had
2693cdf0e10cSrcweir     // an external value binding in place.
2694cdf0e10cSrcweir     doFormListening( true );
2695cdf0e10cSrcweir 
2696cdf0e10cSrcweir     // re-connect to database column of the new parent
2697cdf0e10cSrcweir     if ( m_xAmbientForm.is() && m_xAmbientForm->isLoaded() )
2698cdf0e10cSrcweir         impl_connectDatabaseColumn_noNotify( false );
2699cdf0e10cSrcweir 
2700cdf0e10cSrcweir     // tell the derivee
2701cdf0e10cSrcweir     onDisconnectedExternalValue();
2702cdf0e10cSrcweir }
2703cdf0e10cSrcweir 
2704cdf0e10cSrcweir //--------------------------------------------------------------------
2705cdf0e10cSrcweir void SAL_CALL OBoundControlModel::setValueBinding( const Reference< XValueBinding >& _rxBinding ) throw (IncompatibleTypesException, RuntimeException)
2706cdf0e10cSrcweir {
2707cdf0e10cSrcweir     OSL_PRECOND( m_bSupportsExternalBinding, "OBoundControlModel::setValueBinding: How did you reach this method?" );
2708cdf0e10cSrcweir         // the interface for this method should not have been exposed if we do not
2709cdf0e10cSrcweir         // support binding to external data
2710cdf0e10cSrcweir 
2711cdf0e10cSrcweir     if ( !impl_approveValueBinding_nolock( _rxBinding ) )
2712cdf0e10cSrcweir     {
2713cdf0e10cSrcweir         throw IncompatibleTypesException(
2714cdf0e10cSrcweir             FRM_RES_STRING( RID_STR_INCOMPATIBLE_TYPES ),
2715cdf0e10cSrcweir             *this
2716cdf0e10cSrcweir         );
2717cdf0e10cSrcweir     }
2718cdf0e10cSrcweir 
2719cdf0e10cSrcweir     ControlModelLock aLock( *this );
2720cdf0e10cSrcweir 
2721cdf0e10cSrcweir     // since a ValueBinding overrules any potentially active database binding, the change in a ValueBinding
2722cdf0e10cSrcweir     // might trigger a change in our BoundField.
2723cdf0e10cSrcweir     FieldChangeNotifier aBoundFieldNotifier( aLock );
2724cdf0e10cSrcweir 
2725cdf0e10cSrcweir     // disconnect from the old binding
2726cdf0e10cSrcweir     if ( hasExternalValueBinding() )
2727cdf0e10cSrcweir         disconnectExternalValueBinding( );
2728cdf0e10cSrcweir 
2729cdf0e10cSrcweir     // connect to the new binding
2730cdf0e10cSrcweir     if ( _rxBinding.is() )
2731cdf0e10cSrcweir         connectExternalValueBinding( _rxBinding, aLock );
2732cdf0e10cSrcweir }
2733cdf0e10cSrcweir 
2734cdf0e10cSrcweir //--------------------------------------------------------------------
2735cdf0e10cSrcweir Reference< XValueBinding > SAL_CALL OBoundControlModel::getValueBinding(  ) throw (RuntimeException)
2736cdf0e10cSrcweir {
2737cdf0e10cSrcweir     ::osl::MutexGuard aGuard( m_aMutex );
2738cdf0e10cSrcweir     OSL_PRECOND( m_bSupportsExternalBinding, "OBoundControlModel::getValueBinding: How did you reach this method?" );
2739cdf0e10cSrcweir         // the interface for this method should not have been exposed if we do not
2740cdf0e10cSrcweir         // support binding to external data
2741cdf0e10cSrcweir 
2742cdf0e10cSrcweir     return m_xExternalBinding;
2743cdf0e10cSrcweir }
2744cdf0e10cSrcweir 
2745cdf0e10cSrcweir //--------------------------------------------------------------------
2746cdf0e10cSrcweir void SAL_CALL OBoundControlModel::modified( const EventObject& _rEvent ) throw ( RuntimeException )
2747cdf0e10cSrcweir {
2748cdf0e10cSrcweir     ControlModelLock aLock( *this );
2749cdf0e10cSrcweir 
2750cdf0e10cSrcweir     OSL_PRECOND( hasExternalValueBinding(), "OBoundControlModel::modified: Where did this come from?" );
2751cdf0e10cSrcweir     if ( !m_bTransferingValue && ( m_xExternalBinding == _rEvent.Source ) && m_xExternalBinding.is() )
2752cdf0e10cSrcweir     {
2753cdf0e10cSrcweir         transferExternalValueToControl( aLock );
2754cdf0e10cSrcweir     }
2755cdf0e10cSrcweir }
2756cdf0e10cSrcweir 
2757cdf0e10cSrcweir //--------------------------------------------------------------------
2758cdf0e10cSrcweir void OBoundControlModel::transferDbValueToControl( )
2759cdf0e10cSrcweir {
2760cdf0e10cSrcweir     try
2761cdf0e10cSrcweir     {
2762cdf0e10cSrcweir         setControlValue( translateDbColumnToControlValue(), eDbColumnBinding );
2763cdf0e10cSrcweir     }
2764cdf0e10cSrcweir     catch( const Exception& )
2765cdf0e10cSrcweir     {
2766cdf0e10cSrcweir     	DBG_UNHANDLED_EXCEPTION();
2767cdf0e10cSrcweir     }
2768cdf0e10cSrcweir }
2769cdf0e10cSrcweir 
2770cdf0e10cSrcweir //------------------------------------------------------------------------------
2771cdf0e10cSrcweir void OBoundControlModel::transferExternalValueToControl( ControlModelLock& _rInstanceLock )
2772cdf0e10cSrcweir {
2773cdf0e10cSrcweir         Reference< XValueBinding > xExternalBinding( m_xExternalBinding );
2774cdf0e10cSrcweir         Type aValueExchangeType( getExternalValueType() );
2775cdf0e10cSrcweir 
2776cdf0e10cSrcweir         _rInstanceLock.release();
2777cdf0e10cSrcweir         // >>>>>>>> ----- UNSAFE ----- >>>>>>>>
2778cdf0e10cSrcweir         Any aExternalValue;
2779cdf0e10cSrcweir         try
2780cdf0e10cSrcweir         {
2781cdf0e10cSrcweir             aExternalValue = xExternalBinding->getValue( aValueExchangeType );
2782cdf0e10cSrcweir         }
2783cdf0e10cSrcweir         catch( const Exception& )
2784cdf0e10cSrcweir         {
2785cdf0e10cSrcweir             DBG_UNHANDLED_EXCEPTION();
2786cdf0e10cSrcweir         }
2787cdf0e10cSrcweir         // <<<<<<<< ----- UNSAFE ----- <<<<<<<<
2788cdf0e10cSrcweir         _rInstanceLock.acquire();
2789cdf0e10cSrcweir 
2790cdf0e10cSrcweir         setControlValue( translateExternalValueToControlValue( aExternalValue ), eExternalBinding );
2791cdf0e10cSrcweir }
2792cdf0e10cSrcweir 
2793cdf0e10cSrcweir //------------------------------------------------------------------------------
2794cdf0e10cSrcweir void OBoundControlModel::transferControlValueToExternal( ControlModelLock& _rInstanceLock )
2795cdf0e10cSrcweir {
2796cdf0e10cSrcweir     OSL_PRECOND( m_bSupportsExternalBinding && hasExternalValueBinding(),
2797cdf0e10cSrcweir         "OBoundControlModel::transferControlValueToExternal: precondition not met!" );
2798cdf0e10cSrcweir 
2799cdf0e10cSrcweir     if ( m_xExternalBinding.is() )
2800cdf0e10cSrcweir     {
2801cdf0e10cSrcweir         Any aExternalValue( translateControlValueToExternalValue() );
2802cdf0e10cSrcweir         m_bTransferingValue = sal_True;
2803cdf0e10cSrcweir 
2804cdf0e10cSrcweir         _rInstanceLock.release();
2805cdf0e10cSrcweir          // >>>>>>>> ----- UNSAFE ----- >>>>>>>>
2806cdf0e10cSrcweir         try
2807cdf0e10cSrcweir         {
2808cdf0e10cSrcweir             m_xExternalBinding->setValue( aExternalValue );
2809cdf0e10cSrcweir         }
2810cdf0e10cSrcweir         catch( const Exception& )
2811cdf0e10cSrcweir         {
2812cdf0e10cSrcweir         	DBG_UNHANDLED_EXCEPTION();
2813cdf0e10cSrcweir         }
2814cdf0e10cSrcweir         // <<<<<<<< ----- UNSAFE ----- <<<<<<<<
2815cdf0e10cSrcweir         _rInstanceLock.acquire();
2816cdf0e10cSrcweir 
2817cdf0e10cSrcweir         m_bTransferingValue = sal_False;
2818cdf0e10cSrcweir     }
2819cdf0e10cSrcweir }
2820cdf0e10cSrcweir 
2821cdf0e10cSrcweir // -----------------------------------------------------------------------------
2822cdf0e10cSrcweir Sequence< Type > OBoundControlModel::getSupportedBindingTypes()
2823cdf0e10cSrcweir {
2824cdf0e10cSrcweir     return Sequence< Type >( &m_aValuePropertyType, 1 );
2825cdf0e10cSrcweir }
2826cdf0e10cSrcweir 
2827cdf0e10cSrcweir //-----------------------------------------------------------------------------
2828cdf0e10cSrcweir void OBoundControlModel::calculateExternalValueType()
2829cdf0e10cSrcweir {
2830cdf0e10cSrcweir     m_aExternalValueType = Type();
2831cdf0e10cSrcweir     if ( !m_xExternalBinding.is() )
2832cdf0e10cSrcweir         return;
2833cdf0e10cSrcweir 
2834cdf0e10cSrcweir     Sequence< Type > aTypeCandidates( getSupportedBindingTypes() );
2835cdf0e10cSrcweir     for (   const Type* pTypeCandidate = aTypeCandidates.getConstArray();
2836cdf0e10cSrcweir             pTypeCandidate != aTypeCandidates.getConstArray() + aTypeCandidates.getLength();
2837cdf0e10cSrcweir             ++pTypeCandidate
2838cdf0e10cSrcweir         )
2839cdf0e10cSrcweir     {
2840cdf0e10cSrcweir         if ( m_xExternalBinding->supportsType( *pTypeCandidate ) )
2841cdf0e10cSrcweir         {
2842cdf0e10cSrcweir             m_aExternalValueType = *pTypeCandidate;
2843cdf0e10cSrcweir             break;
2844cdf0e10cSrcweir         }
2845cdf0e10cSrcweir     }
2846cdf0e10cSrcweir }
2847cdf0e10cSrcweir 
2848cdf0e10cSrcweir //-----------------------------------------------------------------------------
2849cdf0e10cSrcweir Any OBoundControlModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const
2850cdf0e10cSrcweir {
2851cdf0e10cSrcweir     OSL_PRECOND( m_bSupportsExternalBinding && hasExternalValueBinding(),
2852cdf0e10cSrcweir         "OBoundControlModel::translateExternalValueToControlValue: precondition not met!" );
2853cdf0e10cSrcweir 
2854cdf0e10cSrcweir     Any aControlValue( _rExternalValue );
2855cdf0e10cSrcweir 
2856cdf0e10cSrcweir     // if the external value is VOID, and our value property is not allowed to be VOID,
2857cdf0e10cSrcweir     // then default-construct a value
2858cdf0e10cSrcweir     if ( !aControlValue.hasValue() && !m_bValuePropertyMayBeVoid )
2859cdf0e10cSrcweir         aControlValue.setValue( NULL, m_aValuePropertyType );
2860cdf0e10cSrcweir 
2861cdf0e10cSrcweir     // outta here
2862cdf0e10cSrcweir     return aControlValue;
2863cdf0e10cSrcweir }
2864cdf0e10cSrcweir 
2865cdf0e10cSrcweir //------------------------------------------------------------------------------
2866cdf0e10cSrcweir Any OBoundControlModel::translateControlValueToExternalValue( ) const
2867cdf0e10cSrcweir {
2868cdf0e10cSrcweir     return getControlValue( );
2869cdf0e10cSrcweir }
2870cdf0e10cSrcweir 
2871cdf0e10cSrcweir //------------------------------------------------------------------------------
2872cdf0e10cSrcweir Any OBoundControlModel::translateControlValueToValidatableValue( ) const
2873cdf0e10cSrcweir {
2874cdf0e10cSrcweir     OSL_PRECOND( m_xValidator.is(), "OBoundControlModel::translateControlValueToValidatableValue: no validator, so why should I?" );
2875cdf0e10cSrcweir     if ( ( m_xValidator == m_xExternalBinding ) && m_xValidator.is() )
2876cdf0e10cSrcweir         return translateControlValueToExternalValue();
2877cdf0e10cSrcweir     return getControlValue();
2878cdf0e10cSrcweir }
2879cdf0e10cSrcweir 
2880cdf0e10cSrcweir //------------------------------------------------------------------------------
2881cdf0e10cSrcweir Any OBoundControlModel::getControlValue( ) const
2882cdf0e10cSrcweir {
2883cdf0e10cSrcweir 	OSL_PRECOND( m_xAggregateFastSet.is() && m_xAggregateSet.is(),
2884cdf0e10cSrcweir         "OBoundControlModel::getControlValue: invalid aggregate !" );
2885cdf0e10cSrcweir     OSL_PRECOND( m_sValuePropertyName.getLength() || ( m_nValuePropertyAggregateHandle != -1 ),
2886cdf0e10cSrcweir         "OBoundControlModel::getControlValue: please override if you have own value property handling!" );
2887cdf0e10cSrcweir 
2888cdf0e10cSrcweir     // determine the current control value
2889cdf0e10cSrcweir     Any aControlValue;
2890cdf0e10cSrcweir     if ( ( m_nValuePropertyAggregateHandle != -1 ) && m_xAggregateFastSet.is() )
2891cdf0e10cSrcweir     {
2892cdf0e10cSrcweir         aControlValue = m_xAggregateFastSet->getFastPropertyValue( m_nValuePropertyAggregateHandle );
2893cdf0e10cSrcweir     }
2894cdf0e10cSrcweir     else if ( m_sValuePropertyName.getLength() && m_xAggregateSet.is() )
2895cdf0e10cSrcweir     {
2896cdf0e10cSrcweir         aControlValue = m_xAggregateSet->getPropertyValue( m_sValuePropertyName );
2897cdf0e10cSrcweir     }
2898cdf0e10cSrcweir 
2899cdf0e10cSrcweir     return aControlValue;
2900cdf0e10cSrcweir }
2901cdf0e10cSrcweir 
2902cdf0e10cSrcweir //--------------------------------------------------------------------
2903cdf0e10cSrcweir void OBoundControlModel::connectValidator( const Reference< XValidator >& _rxValidator )
2904cdf0e10cSrcweir {
2905cdf0e10cSrcweir     OSL_PRECOND( _rxValidator.is(), "OBoundControlModel::connectValidator: invalid validator instance!" );
2906cdf0e10cSrcweir     OSL_PRECOND( !hasValidator( ), "OBoundControlModel::connectValidator: precond not met (have a validator currently)!" );
2907cdf0e10cSrcweir 
2908cdf0e10cSrcweir     m_xValidator = _rxValidator;
2909cdf0e10cSrcweir 
2910cdf0e10cSrcweir     // add as value listener so we get notified when the value changes
2911cdf0e10cSrcweir     if ( m_xValidator.is() )
2912cdf0e10cSrcweir     {
2913cdf0e10cSrcweir         try
2914cdf0e10cSrcweir         {
2915cdf0e10cSrcweir             m_xValidator->addValidityConstraintListener( this );
2916cdf0e10cSrcweir         }
2917cdf0e10cSrcweir         catch( const RuntimeException& )
2918cdf0e10cSrcweir         {
2919cdf0e10cSrcweir         }
2920cdf0e10cSrcweir     }
2921cdf0e10cSrcweir 
2922cdf0e10cSrcweir     onConnectedValidator( );
2923cdf0e10cSrcweir }
2924cdf0e10cSrcweir 
2925cdf0e10cSrcweir //--------------------------------------------------------------------
2926cdf0e10cSrcweir void OBoundControlModel::disconnectValidator( )
2927cdf0e10cSrcweir {
2928cdf0e10cSrcweir     OSL_PRECOND( hasValidator( ), "OBoundControlModel::connectValidator: precond not met (don't have a validator currently)!" );
2929cdf0e10cSrcweir 
2930cdf0e10cSrcweir     // add as value listener so we get notified when the value changes
2931cdf0e10cSrcweir     if ( m_xValidator.is() )
2932cdf0e10cSrcweir     {
2933cdf0e10cSrcweir         try
2934cdf0e10cSrcweir         {
2935cdf0e10cSrcweir             m_xValidator->removeValidityConstraintListener( this );
2936cdf0e10cSrcweir         }
2937cdf0e10cSrcweir         catch( const RuntimeException& )
2938cdf0e10cSrcweir         {
2939cdf0e10cSrcweir         }
2940cdf0e10cSrcweir     }
2941cdf0e10cSrcweir 
2942cdf0e10cSrcweir     m_xValidator.clear();
2943cdf0e10cSrcweir 
2944cdf0e10cSrcweir     onDisconnectedValidator( );
2945cdf0e10cSrcweir }
2946cdf0e10cSrcweir 
2947cdf0e10cSrcweir //--------------------------------------------------------------------
2948cdf0e10cSrcweir void SAL_CALL OBoundControlModel::setValidator( const Reference< XValidator >& _rxValidator ) throw (VetoException,RuntimeException)
2949cdf0e10cSrcweir {
2950cdf0e10cSrcweir     ::osl::ClearableMutexGuard aGuard( m_aMutex );
2951cdf0e10cSrcweir     OSL_PRECOND( m_bSupportsValidation, "OBoundControlModel::setValidator: How did you reach this method?" );
2952cdf0e10cSrcweir         // the interface for this method should not have been exposed if we do not
2953cdf0e10cSrcweir         // support validation
2954cdf0e10cSrcweir 
2955cdf0e10cSrcweir     // early out if the validator does not change
2956cdf0e10cSrcweir     if( _rxValidator == m_xValidator )
2957cdf0e10cSrcweir         return;
2958cdf0e10cSrcweir 
2959cdf0e10cSrcweir     if ( m_xValidator.is() && ( m_xValidator == m_xExternalBinding ) )
2960cdf0e10cSrcweir         throw VetoException(
2961cdf0e10cSrcweir             FRM_RES_STRING( RID_STR_INVALID_VALIDATOR ),
2962cdf0e10cSrcweir             *this
2963cdf0e10cSrcweir         );
2964cdf0e10cSrcweir 
2965cdf0e10cSrcweir     // disconnect from the old validator
2966cdf0e10cSrcweir     if ( hasValidator() )
2967cdf0e10cSrcweir         disconnectValidator( );
2968cdf0e10cSrcweir 
2969cdf0e10cSrcweir     // connect to the new validator
2970cdf0e10cSrcweir     if ( _rxValidator.is() )
2971cdf0e10cSrcweir         connectValidator( _rxValidator );
2972cdf0e10cSrcweir }
2973cdf0e10cSrcweir 
2974cdf0e10cSrcweir //--------------------------------------------------------------------
2975cdf0e10cSrcweir Reference< XValidator > SAL_CALL OBoundControlModel::getValidator(  ) throw (RuntimeException)
2976cdf0e10cSrcweir {
2977cdf0e10cSrcweir     ::osl::MutexGuard aGuard( m_aMutex );
2978cdf0e10cSrcweir     OSL_PRECOND( m_bSupportsValidation, "OBoundControlModel::getValidator: How did you reach this method?" );
2979cdf0e10cSrcweir         // the interface for this method should not have been exposed if we do not
2980cdf0e10cSrcweir         // support validation
2981cdf0e10cSrcweir 
2982cdf0e10cSrcweir     return m_xValidator;
2983cdf0e10cSrcweir }
2984cdf0e10cSrcweir 
2985cdf0e10cSrcweir //--------------------------------------------------------------------
2986cdf0e10cSrcweir void SAL_CALL OBoundControlModel::validityConstraintChanged( const EventObject& /*Source*/ ) throw (RuntimeException)
2987cdf0e10cSrcweir {
2988cdf0e10cSrcweir     ::osl::ClearableMutexGuard aGuard( m_aMutex );
2989cdf0e10cSrcweir     OSL_PRECOND( m_bSupportsValidation, "OBoundControlModel::validityConstraintChanged: How did you reach this method?" );
2990cdf0e10cSrcweir         // the interface for this method should not have been exposed if we do not
2991cdf0e10cSrcweir         // support validation
2992cdf0e10cSrcweir 
2993cdf0e10cSrcweir     recheckValidity( false );
2994cdf0e10cSrcweir }
2995cdf0e10cSrcweir 
2996cdf0e10cSrcweir //--------------------------------------------------------------------
2997cdf0e10cSrcweir sal_Bool SAL_CALL OBoundControlModel::isValid(  ) throw (RuntimeException)
2998cdf0e10cSrcweir {
2999cdf0e10cSrcweir     return m_bIsCurrentValueValid;
3000cdf0e10cSrcweir }
3001cdf0e10cSrcweir 
3002cdf0e10cSrcweir //--------------------------------------------------------------------
3003cdf0e10cSrcweir ::com::sun::star::uno::Any OBoundControlModel::getCurrentFormComponentValue() const
3004cdf0e10cSrcweir {
3005cdf0e10cSrcweir     if ( hasValidator() )
3006cdf0e10cSrcweir         return translateControlValueToValidatableValue();
3007cdf0e10cSrcweir     return getControlValue();
3008cdf0e10cSrcweir }
3009cdf0e10cSrcweir 
3010cdf0e10cSrcweir //--------------------------------------------------------------------
3011cdf0e10cSrcweir Any SAL_CALL OBoundControlModel::getCurrentValue(  ) throw (RuntimeException)
3012cdf0e10cSrcweir {
3013cdf0e10cSrcweir     ::osl::MutexGuard aGuard( m_aMutex );
3014cdf0e10cSrcweir     return getCurrentFormComponentValue();
3015cdf0e10cSrcweir }
3016cdf0e10cSrcweir 
3017cdf0e10cSrcweir //--------------------------------------------------------------------
3018cdf0e10cSrcweir void SAL_CALL OBoundControlModel::addFormComponentValidityListener( const Reference< validation::XFormComponentValidityListener >& Listener ) throw (NullPointerException, RuntimeException)
3019cdf0e10cSrcweir {
3020cdf0e10cSrcweir     if ( Listener.is() )
3021cdf0e10cSrcweir         m_aFormComponentListeners.addInterface( Listener );
3022cdf0e10cSrcweir }
3023cdf0e10cSrcweir 
3024cdf0e10cSrcweir //--------------------------------------------------------------------
3025cdf0e10cSrcweir void SAL_CALL OBoundControlModel::removeFormComponentValidityListener( const Reference< validation::XFormComponentValidityListener >& Listener ) throw (NullPointerException, RuntimeException)
3026cdf0e10cSrcweir {
3027cdf0e10cSrcweir     if ( Listener.is() )
3028cdf0e10cSrcweir         m_aFormComponentListeners.removeInterface( Listener );
3029cdf0e10cSrcweir }
3030cdf0e10cSrcweir 
3031cdf0e10cSrcweir //--------------------------------------------------------------------
3032cdf0e10cSrcweir void OBoundControlModel::recheckValidity( bool _bForceNotification )
3033cdf0e10cSrcweir {
3034cdf0e10cSrcweir     try
3035cdf0e10cSrcweir     {
3036cdf0e10cSrcweir         sal_Bool bIsCurrentlyValid = sal_True;
3037cdf0e10cSrcweir         if ( hasValidator() )
3038cdf0e10cSrcweir             bIsCurrentlyValid = m_xValidator->isValid( translateControlValueToValidatableValue() );
3039cdf0e10cSrcweir 
3040cdf0e10cSrcweir         if ( ( bIsCurrentlyValid != m_bIsCurrentValueValid ) || _bForceNotification )
3041cdf0e10cSrcweir         {
3042cdf0e10cSrcweir             m_bIsCurrentValueValid = bIsCurrentlyValid;
3043cdf0e10cSrcweir 
3044cdf0e10cSrcweir             // release our mutex for the notifications
3045cdf0e10cSrcweir             MutexRelease aRelease( m_aMutex );
3046cdf0e10cSrcweir             m_aFormComponentListeners.notifyEach( &validation::XFormComponentValidityListener::componentValidityChanged, EventObject( *this ) );
3047cdf0e10cSrcweir         }
3048cdf0e10cSrcweir     }
3049cdf0e10cSrcweir     catch( const Exception& )
3050cdf0e10cSrcweir     {
3051cdf0e10cSrcweir     	OSL_ENSURE( sal_False, "OBoundControlModel::recheckValidity: caught an exception!" );
3052cdf0e10cSrcweir     }
3053cdf0e10cSrcweir }
3054cdf0e10cSrcweir 
3055cdf0e10cSrcweir //------------------------------------------------------------------------------
3056cdf0e10cSrcweir void OBoundControlModel::describeFixedProperties( Sequence< Property >& _rProps ) const
3057cdf0e10cSrcweir {
3058cdf0e10cSrcweir     BEGIN_DESCRIBE_PROPERTIES( 5, OControlModel )
3059cdf0e10cSrcweir         DECL_PROP1      ( CONTROLSOURCE,           ::rtl::OUString,     BOUND );
3060cdf0e10cSrcweir         DECL_IFACE_PROP3( BOUNDFIELD,               XPropertySet,       BOUND, READONLY, TRANSIENT );
3061cdf0e10cSrcweir         DECL_IFACE_PROP2( CONTROLLABEL,             XPropertySet,       BOUND, MAYBEVOID );
3062cdf0e10cSrcweir         DECL_PROP2      ( CONTROLSOURCEPROPERTY,    ::rtl::OUString,    READONLY, TRANSIENT );
3063cdf0e10cSrcweir         DECL_BOOL_PROP1 ( INPUT_REQUIRED,                               BOUND );
3064cdf0e10cSrcweir     END_DESCRIBE_PROPERTIES()
3065cdf0e10cSrcweir }
3066cdf0e10cSrcweir 
3067cdf0e10cSrcweir // -----------------------------------------------------------------------------
3068cdf0e10cSrcweir 
3069cdf0e10cSrcweir //.........................................................................
3070cdf0e10cSrcweir }
3071cdf0e10cSrcweir //... namespace frm .......................................................
3072cdf0e10cSrcweir 
3073