xref: /trunk/main/forms/source/component/FormattedFieldWrapper.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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