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 :
29 : //.........................................................................
30 : namespace frm
31 : {
32 : using namespace ::com::sun::star::uno;
33 : using namespace ::com::sun::star::sdb;
34 : using namespace ::com::sun::star::sdbc;
35 : using namespace ::com::sun::star::sdbcx;
36 : using namespace ::com::sun::star::beans;
37 : using namespace ::com::sun::star::container;
38 : using namespace ::com::sun::star::form;
39 : using namespace ::com::sun::star::awt;
40 : using namespace ::com::sun::star::io;
41 : using namespace ::com::sun::star::lang;
42 : using namespace ::com::sun::star::util;
43 :
44 : //==================================================================
45 : // OFormattedFieldWrapper
46 : //==================================================================
47 : DBG_NAME(OFormattedFieldWrapper)
48 :
49 0 : InterfaceRef SAL_CALL OFormattedFieldWrapper_CreateInstance_ForceFormatted(const Reference<XMultiServiceFactory>& _rxFactory)
50 : {
51 0 : return OFormattedFieldWrapper::createFormattedFieldWrapper(_rxFactory, true);
52 : }
53 :
54 0 : InterfaceRef SAL_CALL OFormattedFieldWrapper_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory)
55 : {
56 0 : return OFormattedFieldWrapper::createFormattedFieldWrapper(_rxFactory, false);
57 : }
58 :
59 0 : OFormattedFieldWrapper::OFormattedFieldWrapper(const Reference<XMultiServiceFactory>& _rxFactory)
60 0 : :m_xServiceFactory(_rxFactory)
61 : {
62 : DBG_CTOR(OFormattedFieldWrapper, NULL);
63 0 : }
64 :
65 0 : InterfaceRef OFormattedFieldWrapper::createFormattedFieldWrapper(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory, bool bActAsFormatted)
66 : {
67 0 : OFormattedFieldWrapper *pRef = new OFormattedFieldWrapper(_rxFactory);
68 :
69 0 : if (bActAsFormatted)
70 : {
71 : // instantiate an FormattedModel
72 0 : InterfaceRef xFormattedModel;
73 : // (instantiate it directly ..., as the OFormattedModel isn't
74 : // registered for any service names anymore)
75 0 : OFormattedModel* pModel = new OFormattedModel(pRef->m_xServiceFactory);
76 0 : query_interface(static_cast<XWeak*>(pModel), xFormattedModel);
77 :
78 0 : pRef->m_xAggregate = Reference<XAggregation> (xFormattedModel, UNO_QUERY);
79 : OSL_ENSURE(pRef->m_xAggregate.is(), "the OFormattedModel didn't have an XAggregation interface !");
80 :
81 : // _before_ setting the delegator, give it to the member references
82 0 : query_interface(xFormattedModel, pRef->m_xFormattedPart);
83 0 : pRef->m_pEditPart = rtl::Reference< OEditModel >(new OEditModel(pRef->m_xServiceFactory));
84 : }
85 :
86 0 : increment(pRef->m_refCount);
87 :
88 0 : if (pRef->m_xAggregate.is())
89 : { // has to be in it's own block because of the temporary variable created by *this
90 0 : pRef->m_xAggregate->setDelegator(static_cast<XWeak*>(pRef));
91 : }
92 :
93 0 : InterfaceRef xRef(*pRef);
94 0 : decrement(pRef->m_refCount);
95 :
96 0 : return xRef;
97 : }
98 :
99 0 : Reference< XCloneable > SAL_CALL OFormattedFieldWrapper::createClone() throw (RuntimeException)
100 : {
101 0 : ensureAggregate();
102 :
103 0 : rtl::Reference< OFormattedFieldWrapper > xRef(new OFormattedFieldWrapper(m_xServiceFactory));
104 :
105 0 : Reference< XCloneable > xCloneAccess;
106 0 : query_aggregation( m_xAggregate, xCloneAccess );
107 :
108 : // clone the aggregate
109 0 : if ( xCloneAccess.is() )
110 : {
111 0 : Reference< XCloneable > xClone = xCloneAccess->createClone();
112 0 : xRef->m_xAggregate = Reference< XAggregation >(xClone, UNO_QUERY);
113 : OSL_ENSURE(xRef->m_xAggregate.is(), "invalid aggregate cloned !");
114 :
115 0 : query_interface( Reference< XInterface >(xClone.get() ), xRef->m_xFormattedPart);
116 :
117 0 : if ( m_pEditPart.is() )
118 : {
119 0 : xRef->m_pEditPart = rtl::Reference< OEditModel >( new OEditModel(m_pEditPart.get(), m_xServiceFactory));
120 0 : }
121 : }
122 : else
123 : { // the clone source does not yet have an aggregate -> we don't yet need one, too
124 : }
125 :
126 0 : if ( xRef->m_xAggregate.is() )
127 : { // has to be in it's own block because of the temporary variable created by *this
128 0 : xRef->m_xAggregate->setDelegator(static_cast< XWeak* >(xRef.get()));
129 : }
130 :
131 0 : return xRef.get();
132 : }
133 :
134 0 : OFormattedFieldWrapper::~OFormattedFieldWrapper()
135 : {
136 : // release the aggregated object (if any)
137 0 : if (m_xAggregate.is())
138 0 : m_xAggregate->setDelegator(InterfaceRef ());
139 :
140 : DBG_DTOR(OFormattedFieldWrapper, NULL);
141 0 : }
142 :
143 : //------------------------------------------------------------------
144 0 : Any SAL_CALL OFormattedFieldWrapper::queryAggregation(const Type& _rType) throw (RuntimeException)
145 : {
146 0 : Any aReturn;
147 :
148 0 : if (_rType.equals( ::getCppuType( static_cast< Reference< XTypeProvider >* >(NULL) ) ) )
149 : { // a XTypeProvider interface needs a working aggregate - we don't want to give the type provider
150 : // of our base class (OFormattedFieldWrapper_Base) to the caller as it supplies nearly nothing
151 0 : ensureAggregate();
152 0 : if (m_xAggregate.is())
153 0 : aReturn = m_xAggregate->queryAggregation(_rType);
154 : }
155 :
156 0 : if (!aReturn.hasValue())
157 : {
158 0 : aReturn = OFormattedFieldWrapper_Base::queryAggregation(_rType);
159 :
160 0 : if ((_rType.equals( ::getCppuType( static_cast< Reference< XServiceInfo >* >(NULL) ) ) ) && aReturn.hasValue())
161 : { // somebody requested an XServiceInfo interface and our base class provided it
162 : // check our aggregate if it has one, too
163 0 : ensureAggregate();
164 : }
165 :
166 0 : if (!aReturn.hasValue())
167 : {
168 : aReturn = ::cppu::queryInterface( _rType,
169 : static_cast< XPersistObject* >( this ),
170 : static_cast< XCloneable* >( this )
171 0 : );
172 :
173 0 : if (!aReturn.hasValue())
174 : {
175 : // somebody requests an interface other than the basics (XInterface) and other than
176 : // the two we can supply without an aggregate. So ensure
177 : // the aggregate exists.
178 0 : ensureAggregate();
179 0 : if (m_xAggregate.is())
180 0 : aReturn = m_xAggregate->queryAggregation(_rType);
181 : }
182 : }
183 : }
184 :
185 0 : return aReturn;
186 : }
187 :
188 : //------------------------------------------------------------------
189 0 : ::rtl::OUString SAL_CALL OFormattedFieldWrapper::getServiceName() throw(RuntimeException)
190 : {
191 : // return the old compatibility name for an EditModel
192 0 : return FRM_COMPONENT_EDIT;
193 : }
194 :
195 : //------------------------------------------------------------------
196 0 : ::rtl::OUString SAL_CALL OFormattedFieldWrapper::getImplementationName( ) throw (RuntimeException)
197 : {
198 0 : return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.forms.OFormattedFieldWrapper") );
199 : }
200 :
201 : //------------------------------------------------------------------
202 0 : sal_Bool SAL_CALL OFormattedFieldWrapper::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException)
203 : {
204 : DBG_ASSERT(m_xAggregate.is(), "OFormattedFieldWrapper::supportsService: should never have made it 'til here without an aggregate!");
205 0 : Reference< XServiceInfo > xSI;
206 0 : m_xAggregate->queryAggregation(::getCppuType(static_cast< Reference< XServiceInfo >* >(NULL))) >>= xSI;
207 0 : return xSI->supportsService(_rServiceName);
208 : }
209 :
210 : //------------------------------------------------------------------
211 0 : Sequence< ::rtl::OUString > SAL_CALL OFormattedFieldWrapper::getSupportedServiceNames( ) throw (RuntimeException)
212 : {
213 : DBG_ASSERT(m_xAggregate.is(), "OFormattedFieldWrapper::getSupportedServiceNames: should never have made it 'til here without an aggregate!");
214 0 : Reference< XServiceInfo > xSI;
215 0 : m_xAggregate->queryAggregation(::getCppuType(static_cast< Reference< XServiceInfo >* >(NULL))) >>= xSI;
216 0 : return xSI->getSupportedServiceNames();
217 : }
218 :
219 : //------------------------------------------------------------------
220 0 : void SAL_CALL OFormattedFieldWrapper::write(const Reference<XObjectOutputStream>& _rxOutStream) throw( IOException, RuntimeException )
221 : {
222 : // can't write myself
223 0 : ensureAggregate();
224 :
225 : // if we act as real edit field, we can simple forward this write request
226 0 : if (!m_xFormattedPart.is())
227 : {
228 0 : Reference<XPersistObject> xAggregatePersistence;
229 0 : query_aggregation(m_xAggregate, xAggregatePersistence);
230 : DBG_ASSERT(xAggregatePersistence.is(), "OFormattedFieldWrapper::write : don't know how to handle this : can't write !");
231 : // oops ... We gave an XPersistObject interface to the caller but now we aren't an XPersistObject ...
232 0 : if (xAggregatePersistence.is())
233 0 : xAggregatePersistence->write(_rxOutStream);
234 0 : return;
235 : }
236 :
237 : // else we have to write an edit part first
238 : OSL_ENSURE(m_pEditPart.is(), "OFormattedFieldWrapper::write : formatted part without edit part ?");
239 0 : if ( !m_pEditPart.is() )
240 0 : throw RuntimeException( ::rtl::OUString(), *this );
241 :
242 : // for this we transfer the current props of the formatted part to the edit part
243 0 : Reference<XPropertySet> xFormatProps(m_xFormattedPart, UNO_QUERY);
244 0 : Reference<XPropertySet> xEditProps;
245 0 : query_interface(static_cast<XWeak*>(m_pEditPart.get()), xEditProps);
246 :
247 0 : Locale aAppLanguage = Application::GetSettings().GetUILanguageTag().getLocale();
248 0 : dbtools::TransferFormComponentProperties(xFormatProps, xEditProps, aAppLanguage);
249 :
250 : // then write the edit part, after switching to "fake mode"
251 0 : m_pEditPart->enableFormattedWriteFake();
252 0 : m_pEditPart->write(_rxOutStream);
253 0 : m_pEditPart->disableFormattedWriteFake();
254 :
255 : // and finally write the formatted part we're really interested in
256 0 : m_xFormattedPart->write(_rxOutStream);
257 : }
258 :
259 : //------------------------------------------------------------------
260 0 : void SAL_CALL OFormattedFieldWrapper::read(const Reference<XObjectInputStream>& _rxInStream) throw( IOException, RuntimeException )
261 : {
262 0 : if (m_xAggregate.is())
263 : { // we alread did a decision if we're an EditModel or a FormattedModel
264 :
265 : // if we act as formatted, we have to read the edit part first
266 0 : if (m_xFormattedPart.is())
267 : {
268 : // two possible cases:
269 : // a) the stuff was written by a version which didn't work with an Edit header (all intermediate
270 : // versions >5.1 && <=568)
271 : // b) it was written by a version using edit headers
272 : // as we can distinguish a) from b) only after we have read the edit part, we need to remember the
273 : // position
274 0 : Reference<XMarkableStream> xInMarkable(_rxInStream, UNO_QUERY);
275 : DBG_ASSERT(xInMarkable.is(), "OFormattedFieldWrapper::read : can only work with markable streams !");
276 0 : sal_Int32 nBeforeEditPart = xInMarkable->createMark();
277 :
278 0 : m_pEditPart->read(_rxInStream);
279 : // this only works because an edit model can read the stuff written by a formatted model
280 : // (maybe with some assertions) , but not vice versa
281 0 : if (!m_pEditPart->lastReadWasFormattedFake())
282 : { // case a), written with a version without the edit part fake, so seek to the start position, again
283 0 : xInMarkable->jumpToMark(nBeforeEditPart);
284 : }
285 0 : xInMarkable->deleteMark(nBeforeEditPart);
286 : }
287 :
288 0 : Reference<XPersistObject> xAggregatePersistence;
289 0 : query_aggregation(m_xAggregate, xAggregatePersistence);
290 : DBG_ASSERT(xAggregatePersistence.is(), "OFormattedFieldWrapper::read : don't know how to handle this : can't read !");
291 : // oops ... We gave an XPersistObject interface to the caller but now we aren't an XPersistObject ...
292 :
293 0 : if (xAggregatePersistence.is())
294 0 : xAggregatePersistence->read(_rxInStream);
295 0 : return;
296 : }
297 :
298 : // we have to decide from the data within the stream whether we should
299 : // be an EditModel or a FormattedModel
300 :
301 : {
302 : // let an OEditModel do the reading
303 0 : rtl::Reference< OEditModel > pBasicReader(new OEditModel(m_xServiceFactory));
304 0 : pBasicReader->read(_rxInStream);
305 :
306 : // was it really an edit model ?
307 0 : if (!pBasicReader->lastReadWasFormattedFake())
308 : {
309 : // yes -> all fine
310 0 : m_xAggregate = Reference< XAggregation >( pBasicReader.get() );
311 : }
312 : else
313 : { // no -> substitute it with a formatted model
314 : // let the formmatted model do the reading
315 0 : m_xFormattedPart = Reference< XPersistObject >(new OFormattedModel(m_xServiceFactory));
316 0 : m_xFormattedPart->read(_rxInStream);
317 0 : m_pEditPart = pBasicReader;
318 0 : m_xAggregate = Reference< XAggregation >( m_xFormattedPart, UNO_QUERY );
319 0 : }
320 : }
321 :
322 : // do the aggregation
323 0 : increment(m_refCount);
324 0 : if (m_xAggregate.is())
325 : { // has to be in it's own block because of the temporary variable created by *this
326 0 : m_xAggregate->setDelegator(static_cast<XWeak*>(this));
327 : }
328 0 : decrement(m_refCount);
329 : }
330 :
331 : //------------------------------------------------------------------
332 0 : void OFormattedFieldWrapper::ensureAggregate()
333 : {
334 0 : if (m_xAggregate.is())
335 0 : return;
336 :
337 : {
338 : // instantiate an EditModel (the only place where we are allowed to decide that we're an FormattedModel
339 : // is in ::read)
340 0 : InterfaceRef xEditModel = m_xServiceFactory->createInstance(FRM_SUN_COMPONENT_TEXTFIELD);
341 0 : if (!xEditModel.is())
342 : {
343 : // arghhh ... instantiate it directly ... it's dirty, but we really need this aggregate
344 0 : OEditModel* pModel = new OEditModel(m_xServiceFactory);
345 0 : query_interface(static_cast<XWeak*>(pModel), xEditModel);
346 : }
347 :
348 0 : m_xAggregate = Reference<XAggregation> (xEditModel, UNO_QUERY);
349 : DBG_ASSERT(m_xAggregate.is(), "OFormattedFieldWrapper::ensureAggregate : the OEditModel didn't have an XAggregation interface !");
350 :
351 : {
352 0 : Reference< XServiceInfo > xSI(m_xAggregate, UNO_QUERY);
353 0 : if (!xSI.is())
354 : {
355 : OSL_FAIL("OFormattedFieldWrapper::ensureAggregate: the aggregate has no XServiceInfo!");
356 0 : m_xAggregate.clear();
357 0 : }
358 0 : }
359 : }
360 :
361 0 : increment(m_refCount);
362 0 : if (m_xAggregate.is())
363 : { // has to be in it's own block because of the temporary variable created by *this
364 0 : m_xAggregate->setDelegator(static_cast<XWeak*>(this));
365 : }
366 0 : decrement(m_refCount);
367 : }
368 :
369 : //.........................................................................
370 : }
371 : //.........................................................................
372 :
373 :
374 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|