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