merge the formfield patch from ooo-build
[ooovba.git] / forms / source / component / FormattedFieldWrapper.cxx
blob03e64d655502a54679851e18e92fd180bcf4f896
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: FormattedFieldWrapper.cxx,v $
10 * $Revision: 1.15 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_forms.hxx"
33 #include "FormattedFieldWrapper.hxx"
34 #include "Edit.hxx"
35 #include "FormattedField.hxx"
36 #include <tools/debug.hxx>
37 #include "EditBase.hxx"
38 #include "services.hxx"
39 #include <connectivity/dbtools.hxx>
40 #include <vcl/svapp.hxx>
42 //.........................................................................
43 namespace frm
45 using namespace ::com::sun::star::uno;
46 using namespace ::com::sun::star::sdb;
47 using namespace ::com::sun::star::sdbc;
48 using namespace ::com::sun::star::sdbcx;
49 using namespace ::com::sun::star::beans;
50 using namespace ::com::sun::star::container;
51 using namespace ::com::sun::star::form;
52 using namespace ::com::sun::star::awt;
53 using namespace ::com::sun::star::io;
54 using namespace ::com::sun::star::lang;
55 using namespace ::com::sun::star::util;
57 //==================================================================
58 // OFormattedFieldWrapper
59 //==================================================================
60 DBG_NAME(OFormattedFieldWrapper)
61 //------------------------------------------------------------------
62 InterfaceRef SAL_CALL OFormattedFieldWrapper_CreateInstance_ForceFormatted(const Reference<XMultiServiceFactory>& _rxFactory)
64 return *(new OFormattedFieldWrapper(_rxFactory, sal_True));
67 //------------------------------------------------------------------
68 InterfaceRef SAL_CALL OFormattedFieldWrapper_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory)
70 return *(new OFormattedFieldWrapper(_rxFactory, sal_False));
73 //------------------------------------------------------------------
74 OFormattedFieldWrapper::OFormattedFieldWrapper(const Reference<XMultiServiceFactory>& _rxFactory, sal_Bool _bActAsFormatted)
75 :m_xServiceFactory(_rxFactory)
76 ,m_pEditPart(NULL)
78 DBG_CTOR(OFormattedFieldWrapper, NULL);
80 if (_bActAsFormatted)
82 increment(m_refCount);
84 // instantiate an FormattedModel
85 InterfaceRef xFormattedModel;
86 // (instantiate it directly ..., as the OFormattedModel isn't registered for any service names anymore)
87 OFormattedModel* pModel = new OFormattedModel(m_xServiceFactory);
88 query_interface(static_cast<XWeak*>(pModel), xFormattedModel);
90 m_xAggregate = Reference<XAggregation> (xFormattedModel, UNO_QUERY);
91 DBG_ASSERT(m_xAggregate.is(), "OFormattedFieldWrapper::OFormattedFieldWrapper : the OFormattedModel didn't have an XAggregation interface !");
93 // _before_ setting the delegator, give it to the member references
94 query_interface(xFormattedModel, m_xFormattedPart);
95 m_pEditPart = new OEditModel(m_xServiceFactory);
96 m_pEditPart->acquire();
98 if (m_xAggregate.is())
99 { // has to be in it's own block because of the temporary variable created by *this
100 m_xAggregate->setDelegator(static_cast<XWeak*>(this));
102 decrement(m_refCount);
106 //------------------------------------------------------------------
107 OFormattedFieldWrapper::OFormattedFieldWrapper( const OFormattedFieldWrapper* _pCloneSource )
108 :m_xServiceFactory( _pCloneSource->m_xServiceFactory )
109 ,m_pEditPart( NULL )
111 Reference< XCloneable > xCloneAccess;
112 query_aggregation( _pCloneSource->m_xAggregate, xCloneAccess );
114 // clone the aggregate
115 if ( xCloneAccess.is() )
117 increment( m_refCount );
119 Reference< XCloneable > xClone = xCloneAccess->createClone();
120 m_xAggregate = Reference< XAggregation >( xClone, UNO_QUERY );
121 DBG_ASSERT(m_xAggregate.is(), "OFormattedFieldWrapper::OFormattedFieldWrapper : invalid aggregate clone!");
123 query_interface( Reference< XInterface >( xClone.get() ), m_xFormattedPart );
125 if ( _pCloneSource->m_pEditPart )
127 m_pEditPart = new OEditModel( _pCloneSource->m_pEditPart, _pCloneSource->m_xServiceFactory );
128 m_pEditPart->acquire();
131 if ( m_xAggregate.is() )
132 { // has to be in it's own block because of the temporary variable created by *this
133 m_xAggregate->setDelegator( static_cast< XWeak* >( this ) );
135 decrement( m_refCount );
137 else
138 { // the clone source does not yet have an aggregate -> we don't yet need one, too
142 //------------------------------------------------------------------
143 OFormattedFieldWrapper::~OFormattedFieldWrapper()
145 // release the aggregated object (if any)
146 if (m_xAggregate.is())
147 m_xAggregate->setDelegator(InterfaceRef ());
149 if (m_pEditPart)
150 m_pEditPart->release();
152 DBG_DTOR(OFormattedFieldWrapper, NULL);
155 //------------------------------------------------------------------
156 Any SAL_CALL OFormattedFieldWrapper::queryAggregation(const Type& _rType) throw (RuntimeException)
158 Any aReturn;
160 if (_rType.equals( ::getCppuType( static_cast< Reference< XTypeProvider >* >(NULL) ) ) )
161 { // a XTypeProvider interface needs a working aggregate - we don't want to give the type provider
162 // of our base class (OFormattedFieldWrapper_Base) to the caller as it supplies nearly nothing
163 ensureAggregate();
164 if (m_xAggregate.is())
165 aReturn = m_xAggregate->queryAggregation(_rType);
168 if (!aReturn.hasValue())
170 aReturn = OFormattedFieldWrapper_Base::queryAggregation(_rType);
172 if ((_rType.equals( ::getCppuType( static_cast< Reference< XServiceInfo >* >(NULL) ) ) ) && aReturn.hasValue())
173 { // somebody requested an XServiceInfo interface and our base class provided it
174 // check our aggregate if it has one, too
175 ensureAggregate();
178 if (!aReturn.hasValue())
180 aReturn = ::cppu::queryInterface( _rType,
181 static_cast< XPersistObject* >( this ),
182 static_cast< XCloneable* >( this )
185 if (!aReturn.hasValue())
187 // somebody requests an interface other than the basics (XInterface) and other than
188 // the two we can supply without an aggregate. So ensure
189 // the aggregate exists.
190 ensureAggregate();
191 if (m_xAggregate.is())
192 aReturn = m_xAggregate->queryAggregation(_rType);
197 return aReturn;
200 //------------------------------------------------------------------
201 ::rtl::OUString SAL_CALL OFormattedFieldWrapper::getServiceName() throw(RuntimeException)
203 // return the old compatibility name for an EditModel
204 return FRM_COMPONENT_EDIT;
207 //------------------------------------------------------------------
208 ::rtl::OUString SAL_CALL OFormattedFieldWrapper::getImplementationName( ) throw (RuntimeException)
210 return ::rtl::OUString::createFromAscii("com.sun.star.comp.forms.OFormattedFieldWrapper");
213 //------------------------------------------------------------------
214 sal_Bool SAL_CALL OFormattedFieldWrapper::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException)
216 DBG_ASSERT(m_xAggregate.is(), "OFormattedFieldWrapper::supportsService: should never have made it 'til here without an aggregate!");
217 Reference< XServiceInfo > xSI;
218 m_xAggregate->queryAggregation(::getCppuType(static_cast< Reference< XServiceInfo >* >(NULL))) >>= xSI;
219 return xSI->supportsService(_rServiceName);
222 //------------------------------------------------------------------
223 Sequence< ::rtl::OUString > SAL_CALL OFormattedFieldWrapper::getSupportedServiceNames( ) throw (RuntimeException)
225 DBG_ASSERT(m_xAggregate.is(), "OFormattedFieldWrapper::getSupportedServiceNames: should never have made it 'til here without an aggregate!");
226 Reference< XServiceInfo > xSI;
227 m_xAggregate->queryAggregation(::getCppuType(static_cast< Reference< XServiceInfo >* >(NULL))) >>= xSI;
228 return xSI->getSupportedServiceNames();
231 //------------------------------------------------------------------
232 void SAL_CALL OFormattedFieldWrapper::write(const Reference<XObjectOutputStream>& _rxOutStream) throw( IOException, RuntimeException )
234 // can't write myself
235 ensureAggregate();
237 // if we act as real edit field, we can simple forward this write request
238 if (!m_xFormattedPart.is())
240 Reference<XPersistObject> xAggregatePersistence;
241 query_aggregation(m_xAggregate, xAggregatePersistence);
242 DBG_ASSERT(xAggregatePersistence.is(), "OFormattedFieldWrapper::write : don't know how to handle this : can't write !");
243 // oops ... We gave an XPersistObject interface to the caller but now we aren't an XPersistObject ...
244 if (xAggregatePersistence.is())
245 xAggregatePersistence->write(_rxOutStream);
246 return;
249 // else we have to write an edit part first
250 DBG_ASSERT(m_pEditPart, "OFormattedFieldWrapper::write : formatted part without edit part ?");
251 if ( !m_pEditPart )
252 throw RuntimeException( ::rtl::OUString(), *this );
254 // for this we transfer the current props of the formatted part to the edit part
255 Reference<XPropertySet> xFormatProps(m_xFormattedPart, UNO_QUERY);
256 Reference<XPropertySet> xEditProps;
257 query_interface(static_cast<XWeak*>(m_pEditPart), xEditProps);
259 Locale aAppLanguage = Application::GetSettings().GetUILocale();
260 dbtools::TransferFormComponentProperties(xFormatProps, xEditProps, aAppLanguage);
262 // then write the edit part, after switching to "fake mode"
263 m_pEditPart->enableFormattedWriteFake();
264 m_pEditPart->write(_rxOutStream);
265 m_pEditPart->disableFormattedWriteFake();
267 // and finally write the formatted part we're really interested in
268 m_xFormattedPart->write(_rxOutStream);
271 //------------------------------------------------------------------
272 void SAL_CALL OFormattedFieldWrapper::read(const Reference<XObjectInputStream>& _rxInStream) throw( IOException, RuntimeException )
274 if (m_xAggregate.is())
275 { // we alread did a decision if we're an EditModel or a FormattedModel
277 // if we act as formatted, we have to read the edit part first
278 if (m_xFormattedPart.is())
280 // two possible cases:
281 // a) the stuff was written by a version which didn't work with an Edit header (all intermediate
282 // versions >5.1 && <=568)
283 // b) it was written by a version using edit headers
284 // as we can distinguish a) from b) only after we have read the edit part, we need to remember the
285 // position
286 Reference<XMarkableStream> xInMarkable(_rxInStream, UNO_QUERY);
287 DBG_ASSERT(xInMarkable.is(), "OFormattedFieldWrapper::read : can only work with markable streams !");
288 sal_Int32 nBeforeEditPart = xInMarkable->createMark();
290 m_pEditPart->read(_rxInStream);
291 // this only works because an edit model can read the stuff written by a formatted model (maybe with
292 // some assertions) , but not vice versa
293 if (!m_pEditPart->lastReadWasFormattedFake())
294 { // case a), written with a version without the edit part fake, so seek to the start position, again
295 xInMarkable->jumpToMark(nBeforeEditPart);
297 xInMarkable->deleteMark(nBeforeEditPart);
300 Reference<XPersistObject> xAggregatePersistence;
301 query_aggregation(m_xAggregate, xAggregatePersistence);
302 DBG_ASSERT(xAggregatePersistence.is(), "OFormattedFieldWrapper::read : don't know how to handle this : can't read !");
303 // oops ... We gave an XPersistObject interface to the caller but now we aren't an XPersistObject ...
305 if (xAggregatePersistence.is())
306 xAggregatePersistence->read(_rxInStream);
307 return;
310 // we have to decide from the data within the stream whether we should be an EditModel or a FormattedModel
311 OEditBaseModel* pNewAggregate = NULL;
313 // let an OEditModel do the reading
314 OEditModel* pBasicReader = new OEditModel(m_xServiceFactory);
315 Reference< XInterface > xHoldBasicReaderAlive( *pBasicReader );
316 pBasicReader->read(_rxInStream);
318 // was it really an edit model ?
319 if (!pBasicReader->lastReadWasFormattedFake())
320 // yes -> all fine
321 pNewAggregate = pBasicReader;
322 else
323 { // no -> substitute it with a formatted model
325 // let the formmatted model do the reading
326 OFormattedModel* pFormattedReader = new OFormattedModel(m_xServiceFactory);
327 Reference< XInterface > xHoldAliveWhileRead( *pFormattedReader );
328 pFormattedReader->read(_rxInStream);
330 // for the next write (if any) : the FormattedModel and the EditModel parts
331 query_interface(static_cast<XWeak*>(pFormattedReader), m_xFormattedPart);
332 m_pEditPart = pBasicReader;
333 m_pEditPart->acquire();
335 // aggregate the formatted part below
336 pNewAggregate = pFormattedReader;
339 // do the aggregation
340 increment(m_refCount);
342 query_interface(static_cast<XWeak*>(pNewAggregate), m_xAggregate);
343 DBG_ASSERT(m_xAggregate.is(), "OFormattedFieldWrapper::read : the OEditModel didn't have an XAggregation interface !");
345 if (m_xAggregate.is())
346 { // has to be in it's own block because of the temporary variable created by *this
347 m_xAggregate->setDelegator(static_cast<XWeak*>(this));
349 decrement(m_refCount);
352 //------------------------------------------------------------------
353 Reference< XCloneable > SAL_CALL OFormattedFieldWrapper::createClone( ) throw (RuntimeException)
355 ensureAggregate();
357 return new OFormattedFieldWrapper( this );
360 //------------------------------------------------------------------
361 void OFormattedFieldWrapper::ensureAggregate()
363 if (m_xAggregate.is())
364 return;
366 increment(m_refCount);
368 // instantiate an EditModel (the only place where we are allowed to decide that we're an FormattedModel
369 // is in ::read)
370 InterfaceRef xEditModel = m_xServiceFactory->createInstance(FRM_SUN_COMPONENT_TEXTFIELD);
371 if (!xEditModel.is())
373 // arghhh ... instantiate it directly ... it's dirty, but we really need this aggregate
374 OEditModel* pModel = new OEditModel(m_xServiceFactory);
375 query_interface(static_cast<XWeak*>(pModel), xEditModel);
378 m_xAggregate = Reference<XAggregation> (xEditModel, UNO_QUERY);
379 DBG_ASSERT(m_xAggregate.is(), "OFormattedFieldWrapper::ensureAggregate : the OEditModel didn't have an XAggregation interface !");
382 Reference< XServiceInfo > xSI(m_xAggregate, UNO_QUERY);
383 if (!xSI.is())
385 DBG_ERROR("OFormattedFieldWrapper::ensureAggregate: the aggregate has no XServiceInfo!");
386 m_xAggregate.clear();
390 if (m_xAggregate.is())
391 { // has to be in it's own block because of the temporary variable created by *this
392 m_xAggregate->setDelegator(static_cast<XWeak*>(this));
394 decrement(m_refCount);
397 //.........................................................................
399 //.........................................................................