Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "FormattedFieldWrapper.hxx"
21 : #include "Edit.hxx"
22 : #include "FormattedField.hxx"
23 : #include <tools/debug.hxx>
24 : #include "EditBase.hxx"
25 : #include "services.hxx"
26 : #include <connectivity/dbtools.hxx>
27 : #include <vcl/svapp.hxx>
28 : #include <comphelper/processfactory.hxx>
29 :
30 : //.........................................................................
31 : namespace frm
32 : {
33 : using namespace ::com::sun::star::uno;
34 : using namespace ::com::sun::star::sdb;
35 : using namespace ::com::sun::star::sdbc;
36 : using namespace ::com::sun::star::sdbcx;
37 : using namespace ::com::sun::star::beans;
38 : using namespace ::com::sun::star::container;
39 : using namespace ::com::sun::star::form;
40 : using namespace ::com::sun::star::awt;
41 : using namespace ::com::sun::star::io;
42 : using namespace ::com::sun::star::lang;
43 : using namespace ::com::sun::star::util;
44 :
45 : //==================================================================
46 : // OFormattedFieldWrapper
47 : //==================================================================
48 : DBG_NAME(OFormattedFieldWrapper)
49 :
50 15 : Reference<XInterface> SAL_CALL OFormattedFieldWrapper_CreateInstance_ForceFormatted(const Reference<XMultiServiceFactory>& _rxFactory)
51 : {
52 15 : return OFormattedFieldWrapper::createFormattedFieldWrapper( comphelper::getComponentContext(_rxFactory), true);
53 : }
54 :
55 1 : InterfaceRef SAL_CALL OFormattedFieldWrapper_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory)
56 : {
57 1 : return OFormattedFieldWrapper::createFormattedFieldWrapper( comphelper::getComponentContext(_rxFactory), false);
58 : }
59 :
60 16 : OFormattedFieldWrapper::OFormattedFieldWrapper(const Reference<XComponentContext>& _rxFactory)
61 16 : :m_xContext(_rxFactory)
62 : {
63 : DBG_CTOR(OFormattedFieldWrapper, NULL);
64 16 : }
65 :
66 16 : InterfaceRef OFormattedFieldWrapper::createFormattedFieldWrapper(const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext>& _rxFactory, bool bActAsFormatted)
67 : {
68 16 : OFormattedFieldWrapper *pRef = new OFormattedFieldWrapper(_rxFactory);
69 :
70 16 : if (bActAsFormatted)
71 : {
72 : // instantiate an FormattedModel
73 15 : InterfaceRef xFormattedModel;
74 : // (instantiate it directly ..., as the OFormattedModel isn't
75 : // registered for any service names anymore)
76 15 : OFormattedModel* pModel = new OFormattedModel(pRef->m_xContext);
77 15 : query_interface(static_cast<XWeak*>(pModel), xFormattedModel);
78 :
79 15 : pRef->m_xAggregate = Reference<XAggregation> (xFormattedModel, UNO_QUERY);
80 : OSL_ENSURE(pRef->m_xAggregate.is(), "the OFormattedModel didn't have an XAggregation interface !");
81 :
82 : // _before_ setting the delegator, give it to the member references
83 15 : query_interface(xFormattedModel, pRef->m_xFormattedPart);
84 15 : pRef->m_pEditPart = rtl::Reference< OEditModel >(new OEditModel(pRef->m_xContext));
85 : }
86 :
87 16 : increment(pRef->m_refCount);
88 :
89 16 : if (pRef->m_xAggregate.is())
90 : { // has to be in it's own block because of the temporary variable created by *this
91 15 : pRef->m_xAggregate->setDelegator(static_cast<XWeak*>(pRef));
92 : }
93 :
94 16 : InterfaceRef xRef(*pRef);
95 16 : decrement(pRef->m_refCount);
96 :
97 16 : return xRef;
98 : }
99 :
100 0 : Reference< XCloneable > SAL_CALL OFormattedFieldWrapper::createClone() throw (RuntimeException)
101 : {
102 0 : ensureAggregate();
103 :
104 0 : rtl::Reference< OFormattedFieldWrapper > xRef(new OFormattedFieldWrapper(m_xContext));
105 :
106 0 : Reference< XCloneable > xCloneAccess;
107 0 : query_aggregation( m_xAggregate, xCloneAccess );
108 :
109 : // clone the aggregate
110 0 : if ( xCloneAccess.is() )
111 : {
112 0 : Reference< XCloneable > xClone = xCloneAccess->createClone();
113 0 : xRef->m_xAggregate = Reference< XAggregation >(xClone, UNO_QUERY);
114 : OSL_ENSURE(xRef->m_xAggregate.is(), "invalid aggregate cloned !");
115 :
116 0 : query_interface( Reference< XInterface >(xClone.get() ), xRef->m_xFormattedPart);
117 :
118 0 : if ( m_pEditPart.is() )
119 : {
120 0 : xRef->m_pEditPart = rtl::Reference< OEditModel >( new OEditModel(m_pEditPart.get(), m_xContext));
121 0 : }
122 : }
123 : else
124 : { // the clone source does not yet have an aggregate -> we don't yet need one, too
125 : }
126 :
127 0 : if ( xRef->m_xAggregate.is() )
128 : { // has to be in it's own block because of the temporary variable created by *this
129 0 : xRef->m_xAggregate->setDelegator(static_cast< XWeak* >(xRef.get()));
130 : }
131 :
132 0 : return xRef.get();
133 : }
134 :
135 48 : OFormattedFieldWrapper::~OFormattedFieldWrapper()
136 : {
137 : // release the aggregated object (if any)
138 16 : if (m_xAggregate.is())
139 16 : m_xAggregate->setDelegator(InterfaceRef ());
140 :
141 : DBG_DTOR(OFormattedFieldWrapper, NULL);
142 32 : }
143 :
144 : //------------------------------------------------------------------
145 584 : Any SAL_CALL OFormattedFieldWrapper::queryAggregation(const Type& _rType) throw (RuntimeException)
146 : {
147 584 : Any aReturn;
148 :
149 584 : 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 584 : if (!aReturn.hasValue())
158 : {
159 584 : aReturn = OFormattedFieldWrapper_Base::queryAggregation(_rType);
160 :
161 584 : 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 1 : ensureAggregate();
165 : }
166 :
167 584 : if (!aReturn.hasValue())
168 : {
169 942 : aReturn = ::cppu::queryInterface( _rType,
170 : static_cast< XPersistObject* >( this ),
171 : static_cast< XCloneable* >( this )
172 471 : );
173 :
174 471 : 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 471 : ensureAggregate();
180 471 : if (m_xAggregate.is())
181 471 : aReturn = m_xAggregate->queryAggregation(_rType);
182 : }
183 : }
184 : }
185 :
186 584 : return aReturn;
187 : }
188 :
189 : //------------------------------------------------------------------
190 0 : OUString SAL_CALL OFormattedFieldWrapper::getServiceName() throw(RuntimeException)
191 : {
192 : // return the old compatibility name for an EditModel
193 0 : return OUString(FRM_COMPONENT_EDIT);
194 : }
195 :
196 : //------------------------------------------------------------------
197 0 : OUString SAL_CALL OFormattedFieldWrapper::getImplementationName( ) throw (RuntimeException)
198 : {
199 0 : return OUString("com.sun.star.comp.forms.OFormattedFieldWrapper");
200 : }
201 :
202 : //------------------------------------------------------------------
203 1 : sal_Bool SAL_CALL OFormattedFieldWrapper::supportsService( const OUString& _rServiceName ) throw (RuntimeException)
204 : {
205 : DBG_ASSERT(m_xAggregate.is(), "OFormattedFieldWrapper::supportsService: should never have made it 'til here without an aggregate!");
206 1 : Reference< XServiceInfo > xSI;
207 1 : m_xAggregate->queryAggregation(::getCppuType(static_cast< Reference< XServiceInfo >* >(NULL))) >>= xSI;
208 1 : return xSI->supportsService(_rServiceName);
209 : }
210 :
211 : //------------------------------------------------------------------
212 0 : Sequence< 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 : OSL_ENSURE(m_pEditPart.is(), "OFormattedFieldWrapper::write : formatted part without edit part ?");
240 0 : if ( !m_pEditPart.is() )
241 0 : throw RuntimeException( OUString(), *this );
242 :
243 : // for this we transfer the current props of the formatted part to the edit part
244 0 : Reference<XPropertySet> xFormatProps(m_xFormattedPart, UNO_QUERY);
245 0 : Reference<XPropertySet> xEditProps;
246 0 : query_interface(static_cast<XWeak*>(m_pEditPart.get()), xEditProps);
247 :
248 0 : Locale aAppLanguage = Application::GetSettings().GetUILanguageTag().getLocale();
249 0 : dbtools::TransferFormComponentProperties(xFormatProps, xEditProps, aAppLanguage);
250 :
251 : // then write the edit part, after switching to "fake mode"
252 0 : m_pEditPart->enableFormattedWriteFake();
253 0 : m_pEditPart->write(_rxOutStream);
254 0 : m_pEditPart->disableFormattedWriteFake();
255 :
256 : // and finally write the formatted part we're really interested in
257 0 : m_xFormattedPart->write(_rxOutStream);
258 : }
259 :
260 : //------------------------------------------------------------------
261 1 : void SAL_CALL OFormattedFieldWrapper::read(const Reference<XObjectInputStream>& _rxInStream) throw( IOException, RuntimeException )
262 : {
263 1 : SolarMutexGuard g;
264 1 : if (m_xAggregate.is())
265 : { // we alread did a decision if we're an EditModel or a FormattedModel
266 :
267 : // if we act as formatted, we have to read the edit part first
268 0 : if (m_xFormattedPart.is())
269 : {
270 : // two possible cases:
271 : // a) the stuff was written by a version which didn't work with an Edit header (all intermediate
272 : // versions >5.1 && <=568)
273 : // b) it was written by a version using edit headers
274 : // as we can distinguish a) from b) only after we have read the edit part, we need to remember the
275 : // position
276 0 : Reference<XMarkableStream> xInMarkable(_rxInStream, UNO_QUERY);
277 : DBG_ASSERT(xInMarkable.is(), "OFormattedFieldWrapper::read : can only work with markable streams !");
278 0 : sal_Int32 nBeforeEditPart = xInMarkable->createMark();
279 :
280 0 : m_pEditPart->read(_rxInStream);
281 : // this only works because an edit model can read the stuff written by a formatted model
282 : // (maybe with some assertions) , but not vice versa
283 0 : if (!m_pEditPart->lastReadWasFormattedFake())
284 : { // case a), written with a version without the edit part fake, so seek to the start position, again
285 0 : xInMarkable->jumpToMark(nBeforeEditPart);
286 : }
287 0 : xInMarkable->deleteMark(nBeforeEditPart);
288 : }
289 :
290 0 : Reference<XPersistObject> xAggregatePersistence;
291 0 : query_aggregation(m_xAggregate, xAggregatePersistence);
292 : DBG_ASSERT(xAggregatePersistence.is(), "OFormattedFieldWrapper::read : don't know how to handle this : can't read !");
293 : // oops ... We gave an XPersistObject interface to the caller but now we aren't an XPersistObject ...
294 :
295 0 : if (xAggregatePersistence.is())
296 0 : xAggregatePersistence->read(_rxInStream);
297 1 : return;
298 : }
299 :
300 : // we have to decide from the data within the stream whether we should
301 : // be an EditModel or a FormattedModel
302 :
303 : {
304 : // let an OEditModel do the reading
305 1 : rtl::Reference< OEditModel > pBasicReader(new OEditModel(m_xContext));
306 1 : pBasicReader->read(_rxInStream);
307 :
308 : // was it really an edit model ?
309 1 : if (!pBasicReader->lastReadWasFormattedFake())
310 : {
311 : // yes -> all fine
312 1 : m_xAggregate = Reference< XAggregation >( pBasicReader.get() );
313 : }
314 : else
315 : { // no -> substitute it with a formatted model
316 : // let the formmatted model do the reading
317 0 : m_xFormattedPart = Reference< XPersistObject >(new OFormattedModel(m_xContext));
318 0 : m_xFormattedPart->read(_rxInStream);
319 0 : m_pEditPart = pBasicReader;
320 0 : m_xAggregate = Reference< XAggregation >( m_xFormattedPart, UNO_QUERY );
321 1 : }
322 : }
323 :
324 : // do the aggregation
325 1 : increment(m_refCount);
326 1 : if (m_xAggregate.is())
327 : { // has to be in it's own block because of the temporary variable created by *this
328 1 : m_xAggregate->setDelegator(static_cast<XWeak*>(this));
329 : }
330 1 : decrement(m_refCount);
331 : }
332 :
333 : //------------------------------------------------------------------
334 472 : void OFormattedFieldWrapper::ensureAggregate()
335 : {
336 472 : if (m_xAggregate.is())
337 944 : return;
338 :
339 : {
340 : // instantiate an EditModel (the only place where we are allowed to decide that we're an FormattedModel
341 : // is in ::read)
342 0 : InterfaceRef xEditModel = m_xContext->getServiceManager()->createInstanceWithContext(FRM_SUN_COMPONENT_TEXTFIELD, m_xContext);
343 0 : if (!xEditModel.is())
344 : {
345 : // arghhh ... instantiate it directly ... it's dirty, but we really need this aggregate
346 0 : OEditModel* pModel = new OEditModel(m_xContext);
347 0 : query_interface(static_cast<XWeak*>(pModel), xEditModel);
348 : }
349 :
350 0 : m_xAggregate = Reference<XAggregation> (xEditModel, UNO_QUERY);
351 : DBG_ASSERT(m_xAggregate.is(), "OFormattedFieldWrapper::ensureAggregate : the OEditModel didn't have an XAggregation interface !");
352 :
353 : {
354 0 : Reference< XServiceInfo > xSI(m_xAggregate, UNO_QUERY);
355 0 : if (!xSI.is())
356 : {
357 : OSL_FAIL("OFormattedFieldWrapper::ensureAggregate: the aggregate has no XServiceInfo!");
358 0 : m_xAggregate.clear();
359 0 : }
360 0 : }
361 : }
362 :
363 0 : increment(m_refCount);
364 0 : if (m_xAggregate.is())
365 : { // has to be in it's own block because of the temporary variable created by *this
366 0 : m_xAggregate->setDelegator(static_cast<XWeak*>(this));
367 : }
368 0 : decrement(m_refCount);
369 : }
370 :
371 : //.........................................................................
372 72 : }
373 : //.........................................................................
374 :
375 :
376 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|