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