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 "layerexport.hxx"
21 : #include "strings.hxx"
22 : #include <xmloff/xmlexp.hxx>
23 : #include <xmloff/nmspmap.hxx>
24 : #include <xmloff/xmlnmspe.hxx>
25 : #include <xmloff/xmluconv.hxx>
26 : #include <xmloff/xmlprmap.hxx>
27 : #include <xmloff/prhdlfac.hxx>
28 : #include "elementexport.hxx"
29 : #include <xmloff/families.hxx>
30 : #include <xmloff/contextid.hxx>
31 : #include <xmloff/controlpropertyhdl.hxx>
32 : #include <xmloff/maptype.hxx>
33 : #include <tools/diagnose_ex.h>
34 : #include <tools/debug.hxx>
35 : #include "controlpropertymap.hxx"
36 : #include <com/sun/star/container/XIndexAccess.hpp>
37 : #include <com/sun/star/form/XFormsSupplier2.hpp>
38 : #include <com/sun/star/xforms/XFormsSupplier.hpp>
39 : #include <com/sun/star/form/FormComponentType.hpp>
40 : #include <com/sun/star/lang/XServiceInfo.hpp>
41 : #include <com/sun/star/container/XChild.hpp>
42 : #include <com/sun/star/script/XEventAttacherManager.hpp>
43 : #include <com/sun/star/util/NumberFormatsSupplier.hpp>
44 : #include "eventexport.hxx"
45 : #include <xmloff/XMLEventExport.hxx>
46 : #include "formevents.hxx"
47 : #include <xmloff/xmlnumfe.hxx>
48 : #include <xmloff/xformsexport.hxx>
49 : #include <comphelper/processfactory.hxx>
50 :
51 : #include <com/sun/star/text/XText.hpp>
52 :
53 : #include <numeric>
54 :
55 : namespace xmloff
56 : {
57 :
58 : using namespace ::com::sun::star::uno;
59 : using namespace ::com::sun::star::awt;
60 : using namespace ::com::sun::star::lang;
61 : using namespace ::com::sun::star::beans;
62 : using namespace ::com::sun::star::container;
63 : using namespace ::com::sun::star::drawing;
64 : using namespace ::com::sun::star::form;
65 : using namespace ::com::sun::star::script;
66 : using namespace ::com::sun::star::util;
67 : using namespace ::com::sun::star::text;
68 :
69 : typedef ::com::sun::star::xforms::XFormsSupplier XXFormsSupplier;
70 :
71 : //= OFormLayerXMLExport_Impl
72 0 : const OUString& OFormLayerXMLExport_Impl::getControlNumberStyleNamePrefix()
73 : {
74 0 : static const OUString s_sControlNumberStyleNamePrefix("C");
75 0 : return s_sControlNumberStyleNamePrefix;
76 : }
77 :
78 124 : OFormLayerXMLExport_Impl::OFormLayerXMLExport_Impl(SvXMLExport& _rContext)
79 : :m_rContext(_rContext)
80 124 : ,m_pControlNumberStyles(NULL)
81 : {
82 124 : initializePropertyMaps();
83 :
84 : // add our style family to the export context's style pool
85 124 : m_xPropertyHandlerFactory = new OControlPropertyHandlerFactory();
86 124 : ::rtl::Reference< XMLPropertySetMapper > xStylePropertiesMapper = new XMLPropertySetMapper( getControlStylePropertyMap(), m_xPropertyHandlerFactory.get(), true );
87 124 : m_xStyleExportMapper = new OFormComponentStyleExportMapper( xStylePropertiesMapper.get() );
88 :
89 : // our style family
90 : m_rContext.GetAutoStylePool()->AddFamily(
91 124 : XML_STYLE_FAMILY_CONTROL_ID, token::GetXMLToken(token::XML_PARAGRAPH),
92 : m_xStyleExportMapper.get(),
93 : OUString( XML_STYLE_FAMILY_CONTROL_PREFIX )
94 248 : );
95 :
96 : // add our event translation table
97 124 : m_rContext.GetEventExport().AddTranslationTable(g_pFormsEventTranslation);
98 :
99 124 : clear();
100 124 : }
101 :
102 248 : OFormLayerXMLExport_Impl::~OFormLayerXMLExport_Impl()
103 : {
104 248 : }
105 :
106 124 : bool OFormLayerXMLExport_Impl::impl_isFormPageContainingForms(const Reference< XDrawPage >& _rxDrawPage, Reference< XIndexAccess >& _rxForms)
107 : {
108 124 : Reference< XFormsSupplier2 > xFormsSupp(_rxDrawPage, UNO_QUERY);
109 : OSL_ENSURE(xFormsSupp.is(), "OFormLayerXMLExport_Impl::impl_isFormPageContainingForms: invalid draw page (no XFormsSupplier)! Doin' nothing!");
110 124 : if (!xFormsSupp.is())
111 0 : return false;
112 :
113 124 : if ( !xFormsSupp->hasForms() )
114 : // nothing to do at all
115 116 : return false;
116 :
117 8 : _rxForms = Reference< XIndexAccess >(xFormsSupp->getForms(), UNO_QUERY);
118 16 : Reference< XServiceInfo > xSI(_rxForms, UNO_QUERY); // order is important!
119 : OSL_ENSURE(xSI.is(), "OFormLayerXMLExport_Impl::impl_isFormPageContainingForms: invalid collection (must not be NULL and must have a ServiceInfo)!");
120 8 : if (!xSI.is())
121 0 : return false;
122 :
123 8 : if (!xSI->supportsService("com.sun.star.form.Forms"))
124 : {
125 : OSL_FAIL("OFormLayerXMLExport_Impl::impl_isFormPageContainingForms: invalid collection (is no com.sun.star.form.Forms)!");
126 : // nothing to do
127 0 : return false;
128 : }
129 132 : return true;
130 : }
131 :
132 0 : void OFormLayerXMLExport_Impl::exportGridColumn(const Reference< XPropertySet >& _rxColumn,
133 : const Sequence< ScriptEventDescriptor >& _rEvents)
134 : {
135 : // do the exporting
136 0 : OColumnExport aExportImpl(*this, _rxColumn, getControlId( _rxColumn ), _rEvents);
137 0 : aExportImpl.doExport();
138 0 : }
139 :
140 2 : void OFormLayerXMLExport_Impl::exportControl(const Reference< XPropertySet >& _rxControl,
141 : const Sequence< ScriptEventDescriptor >& _rEvents)
142 : {
143 : // the list of the referring controls
144 2 : OUString sReferringControls;
145 2 : MapPropertySet2String::const_iterator aReferring = m_aCurrentPageReferring->second.find(_rxControl);
146 2 : if (aReferring != m_aCurrentPageReferring->second.end())
147 0 : sReferringControls = aReferring->second;
148 :
149 : // the control id (should already have been created in examineForms)
150 4 : OUString sControlId( getControlId( _rxControl ) );
151 :
152 : // do the exporting
153 4 : OControlExport aExportImpl(*this, _rxControl, sControlId, sReferringControls, _rEvents);
154 4 : aExportImpl.doExport();
155 2 : }
156 :
157 2 : void OFormLayerXMLExport_Impl::exportForm(const Reference< XPropertySet >& _rxProps,
158 : const Sequence< ScriptEventDescriptor >& _rEvents)
159 : {
160 : OSL_ENSURE(_rxProps.is(), "OFormLayerXMLExport_Impl::exportForm: invalid property set!");
161 2 : OFormExport aAttributeHandler(*this, _rxProps, _rEvents);
162 2 : aAttributeHandler.doExport();
163 2 : }
164 :
165 2 : ::rtl::Reference< SvXMLExportPropertyMapper > OFormLayerXMLExport_Impl::getStylePropertyMapper()
166 : {
167 2 : return m_xStyleExportMapper;
168 : }
169 :
170 68 : SvXMLExport& OFormLayerXMLExport_Impl::getGlobalContext()
171 : {
172 68 : return m_rContext;
173 : }
174 :
175 6 : void OFormLayerXMLExport_Impl::exportCollectionElements(const Reference< XIndexAccess >& _rxCollection)
176 : {
177 : // step through all the elements of the collection
178 6 : sal_Int32 nElements = _rxCollection->getCount();
179 :
180 6 : Reference< XEventAttacherManager > xElementEventManager(_rxCollection, UNO_QUERY);
181 12 : Sequence< ScriptEventDescriptor > aElementEvents;
182 :
183 12 : Reference< XPropertySetInfo > xPropsInfo;
184 12 : Reference< XIndexAccess > xCurrentContainer;
185 10 : for (sal_Int32 i=0; i<nElements; ++i)
186 : {
187 : try
188 : {
189 : // extract the current element
190 4 : Reference< XPropertySet > xCurrentProps( _rxCollection->getByIndex(i), UNO_QUERY );
191 : OSL_ENSURE(xCurrentProps.is(), "OFormLayerXMLExport_Impl::exportCollectionElements: invalid child element, skipping!");
192 4 : if (!xCurrentProps.is())
193 0 : continue;
194 :
195 : // check if there is a ClassId property on the current element. If so, we assume it to be a control
196 4 : xPropsInfo = xCurrentProps->getPropertySetInfo();
197 : OSL_ENSURE(xPropsInfo.is(), "OFormLayerXMLExport_Impl::exportCollectionElements: no property set info!");
198 4 : if (!xPropsInfo.is())
199 : // without this, a lot of stuff in the export routines may fail
200 0 : continue;
201 :
202 : // if the element is part of a ignore list, we are not allowed to export it
203 4 : if ( m_aIgnoreList.end() != m_aIgnoreList.find( xCurrentProps ) )
204 0 : continue;
205 :
206 4 : if (xElementEventManager.is())
207 4 : aElementEvents = xElementEventManager->getScriptEvents(i);
208 :
209 4 : if (xPropsInfo->hasPropertyByName(PROPERTY_COLUMNSERVICENAME))
210 : {
211 0 : exportGridColumn(xCurrentProps, aElementEvents);
212 : }
213 4 : else if (xPropsInfo->hasPropertyByName(PROPERTY_CLASSID))
214 : {
215 2 : exportControl(xCurrentProps, aElementEvents);
216 : }
217 : else
218 : {
219 2 : exportForm(xCurrentProps, aElementEvents);
220 4 : }
221 : }
222 0 : catch(Exception&)
223 : {
224 : OSL_FAIL("OFormLayerXMLExport_Impl::exportCollectionElements: caught an exception ... skipping the current element!");
225 0 : continue;
226 : }
227 6 : }
228 6 : }
229 :
230 0 : OUString OFormLayerXMLExport_Impl::getObjectStyleName( const Reference< XPropertySet >& _rxObject )
231 : {
232 0 : OUString aObjectStyle;
233 :
234 0 : MapPropertySet2String::const_iterator aObjectStylePos = m_aGridColumnStyles.find( _rxObject );
235 0 : if ( m_aGridColumnStyles.end() != aObjectStylePos )
236 0 : aObjectStyle = aObjectStylePos->second;
237 0 : return aObjectStyle;
238 : }
239 :
240 124 : void OFormLayerXMLExport_Impl::clear()
241 : {
242 124 : m_aControlIds.clear();
243 124 : m_aReferringControls.clear();
244 124 : m_aCurrentPageIds = m_aControlIds.end();
245 124 : m_aCurrentPageReferring = m_aReferringControls.end();
246 :
247 124 : m_aControlNumberFormats.clear();
248 124 : m_aGridColumnStyles.clear();
249 :
250 124 : m_aIgnoreList.clear();
251 124 : }
252 :
253 98 : void OFormLayerXMLExport_Impl::exportAutoControlNumberStyles()
254 : {
255 98 : if ( m_pControlNumberStyles )
256 0 : m_pControlNumberStyles->Export( true );
257 98 : }
258 :
259 117 : void OFormLayerXMLExport_Impl::exportAutoStyles()
260 : {
261 : m_rContext.GetAutoStylePool()->exportXML(
262 : XML_STYLE_FAMILY_CONTROL_ID,
263 117 : m_rContext.GetDocHandler(),
264 117 : m_rContext.GetMM100UnitConverter(),
265 117 : m_rContext.GetNamespaceMap()
266 117 : );
267 117 : }
268 :
269 4 : void OFormLayerXMLExport_Impl::exportForms(const Reference< XDrawPage >& _rxDrawPage)
270 : {
271 : // get the forms collection of the page
272 4 : Reference< XIndexAccess > xCollectionIndex;
273 4 : if (!impl_isFormPageContainingForms(_rxDrawPage, xCollectionIndex))
274 : {
275 4 : return;
276 : }
277 :
278 : #if OSL_DEBUG_LEVEL > 0
279 : bool bPageIsKnown =
280 : #endif
281 4 : implMoveIterators(_rxDrawPage, false);
282 : OSL_ENSURE(bPageIsKnown, "OFormLayerXMLExport_Impl::exportForms: exporting a page which has not been examined!");
283 :
284 : // export forms collection
285 4 : exportCollectionElements(xCollectionIndex);
286 : }
287 :
288 2 : void OFormLayerXMLExport_Impl::exportXForms() const
289 : {
290 : // export XForms models
291 2 : ::exportXForms( m_rContext );
292 2 : }
293 :
294 73 : bool OFormLayerXMLExport_Impl::pageContainsForms( const Reference< XDrawPage >& _rxDrawPage )
295 : {
296 73 : Reference< XFormsSupplier2 > xFormsSupp( _rxDrawPage, UNO_QUERY );
297 : DBG_ASSERT( xFormsSupp.is(), "OFormLayerXMLExport_Impl::pageContainsForms: no XFormsSupplier2!" );
298 73 : return xFormsSupp.is() && xFormsSupp->hasForms();
299 : }
300 :
301 71 : bool OFormLayerXMLExport_Impl::documentContainsXForms() const
302 : {
303 71 : Reference< XXFormsSupplier > xXFormSupp( m_rContext.GetModel(), UNO_QUERY );
304 142 : Reference< XNameContainer > xForms;
305 71 : if ( xXFormSupp.is() )
306 71 : xForms = xXFormSupp->getXForms();
307 142 : return xForms.is() && xForms->hasElements();
308 : }
309 :
310 57 : bool OFormLayerXMLExport_Impl::implMoveIterators(const Reference< XDrawPage >& _rxDrawPage, bool _bClear)
311 : {
312 57 : if (!_rxDrawPage.is())
313 0 : return false;
314 :
315 57 : bool bKnownPage = false;
316 :
317 : // the one for the ids
318 57 : m_aCurrentPageIds = m_aControlIds.find(_rxDrawPage);
319 57 : if (m_aControlIds.end() == m_aCurrentPageIds)
320 : {
321 46 : m_aControlIds[_rxDrawPage] = MapPropertySet2String();
322 46 : m_aCurrentPageIds = m_aControlIds.find(_rxDrawPage);
323 : }
324 : else
325 : {
326 11 : bKnownPage = true;
327 11 : if (_bClear && !m_aCurrentPageIds->second.empty() )
328 0 : m_aCurrentPageIds->second.clear();
329 : }
330 :
331 : // the one for the ids of the referring controls
332 57 : m_aCurrentPageReferring = m_aReferringControls.find(_rxDrawPage);
333 57 : if (m_aReferringControls.end() == m_aCurrentPageReferring)
334 : {
335 46 : m_aReferringControls[_rxDrawPage] = MapPropertySet2String();
336 46 : m_aCurrentPageReferring = m_aReferringControls.find(_rxDrawPage);
337 : }
338 : else
339 : {
340 11 : bKnownPage = true;
341 11 : if (_bClear && !m_aCurrentPageReferring->second.empty() )
342 0 : m_aCurrentPageReferring->second.clear();
343 : }
344 57 : return bKnownPage;
345 : }
346 :
347 49 : bool OFormLayerXMLExport_Impl::seekPage(const Reference< XDrawPage >& _rxDrawPage)
348 : {
349 49 : bool bKnownPage = implMoveIterators( _rxDrawPage, false );
350 49 : if ( bKnownPage )
351 7 : return true;
352 :
353 : // if the page is not yet known, this does not automatically mean that it has
354 : // not been examined. Instead, examineForms returns silently and successfully
355 : // if a page is a XFormsPageSupplier2, but does not have a forms collection
356 : // (This behaviour of examineForms is a performance optimization, to not force
357 : // the page to create a forms container just to see that it's empty.)
358 :
359 : // So, in such a case, seekPage is considered to be successful, too, though the
360 : // page was not yet known
361 42 : Reference< XFormsSupplier2 > xFormsSupp( _rxDrawPage, UNO_QUERY );
362 42 : if ( xFormsSupp.is() && !xFormsSupp->hasForms() )
363 42 : return true;
364 :
365 : // anything else means that the page has not been examined before, or it's no
366 : // valid form page. Both cases are Bad (TM).
367 0 : return false;
368 : }
369 :
370 4 : OUString OFormLayerXMLExport_Impl::getControlId(const Reference< XPropertySet >& _rxControl)
371 : {
372 4 : if (m_aCurrentPageIds == m_aControlIds.end())
373 0 : return OUString();
374 :
375 : OSL_ENSURE(m_aCurrentPageIds->second.end() != m_aCurrentPageIds->second.find(_rxControl),
376 : "OFormLayerXMLExport_Impl::getControlId: can not find the control!");
377 4 : return m_aCurrentPageIds->second[_rxControl];
378 : }
379 :
380 0 : OUString OFormLayerXMLExport_Impl::getImmediateNumberStyle( const Reference< XPropertySet >& _rxObject )
381 : {
382 0 : OUString sNumberStyle;
383 :
384 0 : sal_Int32 nOwnFormatKey = implExamineControlNumberFormat( _rxObject );
385 0 : if ( -1 != nOwnFormatKey )
386 0 : sNumberStyle = getControlNumberStyleExport()->GetStyleName( nOwnFormatKey );
387 :
388 0 : return sNumberStyle;
389 : }
390 :
391 2 : OUString OFormLayerXMLExport_Impl::getControlNumberStyle( const Reference< XPropertySet >& _rxControl )
392 : {
393 2 : OUString sNumberStyle;
394 :
395 2 : MapPropertySet2Int::const_iterator aControlFormatPos = m_aControlNumberFormats.find(_rxControl);
396 2 : if (m_aControlNumberFormats.end() != aControlFormatPos)
397 : {
398 : OSL_ENSURE(m_pControlNumberStyles, "OFormLayerXMLExport_Impl::getControlNumberStyle: have a control which has a format style, but no style exporter!");
399 0 : sNumberStyle = getControlNumberStyleExport()->GetStyleName(aControlFormatPos->second);
400 : }
401 : // it's allowed to ask for a control which does not have format information.
402 : // (This is for performance reasons)
403 :
404 2 : return sNumberStyle;
405 : }
406 :
407 120 : void OFormLayerXMLExport_Impl::examineForms(const Reference< XDrawPage >& _rxDrawPage)
408 : {
409 : // get the forms collection of the page
410 120 : Reference< XIndexAccess > xCollectionIndex;
411 120 : if (!impl_isFormPageContainingForms(_rxDrawPage, xCollectionIndex))
412 : {
413 236 : return;
414 : }
415 :
416 : // move the iterator which specify the currently handled page
417 : #if OSL_DEBUG_LEVEL > 0
418 : bool bPageIsKnown =
419 : #endif
420 4 : implMoveIterators(_rxDrawPage, true);
421 : OSL_ENSURE(!bPageIsKnown, "OFormLayerXMLExport_Impl::examineForms: examining a page twice!");
422 :
423 8 : ::std::stack< Reference< XIndexAccess > > aContainerHistory;
424 8 : ::std::stack< sal_Int32 > aIndexHistory;
425 :
426 8 : Reference< XIndexAccess > xLoop = xCollectionIndex;
427 4 : sal_Int32 nChildPos = 0;
428 4 : do
429 : {
430 8 : if (nChildPos < xLoop->getCount())
431 : {
432 4 : Reference< XPropertySet > xCurrent( xLoop->getByIndex( nChildPos ), UNO_QUERY );
433 : OSL_ENSURE(xCurrent.is(), "OFormLayerXMLExport_Impl::examineForms: invalid child object");
434 4 : if (!xCurrent.is())
435 0 : continue;
436 :
437 4 : if (!checkExamineControl(xCurrent))
438 : {
439 : // step down
440 2 : Reference< XIndexAccess > xNextContainer(xCurrent, UNO_QUERY);
441 : OSL_ENSURE(xNextContainer.is(), "OFormLayerXMLExport_Impl::examineForms: what the heck is this ... no control, no container?");
442 2 : aContainerHistory.push(xLoop);
443 2 : aIndexHistory.push(nChildPos);
444 :
445 2 : xLoop = xNextContainer;
446 2 : nChildPos = -1; // will be incremented below
447 : }
448 4 : ++nChildPos;
449 : }
450 : else
451 : {
452 : // step up
453 10 : while ((nChildPos >= xLoop->getCount()) && !aContainerHistory.empty() )
454 : {
455 2 : xLoop = aContainerHistory.top();
456 2 : aContainerHistory.pop();
457 2 : nChildPos = aIndexHistory.top();
458 2 : aIndexHistory.pop();
459 :
460 2 : ++nChildPos;
461 : }
462 4 : if (nChildPos >= xLoop->getCount())
463 : // exited the loop above because we have no history anymore (0 == aContainerHistory.size()),
464 : // and on the current level there are no more children
465 : // -> leave
466 4 : break;
467 : }
468 : }
469 4 : while (xLoop.is());
470 : }
471 :
472 : namespace
473 : {
474 : struct AccumulateSize : public ::std::binary_function< size_t, MapPropertySet2Map::value_type, size_t >
475 : {
476 2 : size_t operator()( size_t _size, const MapPropertySet2Map::value_type& _map ) const
477 : {
478 2 : return _size + _map.second.size();
479 : }
480 : };
481 :
482 2 : OUString lcl_findFreeControlId( const MapPropertySet2Map& _rAllPagesControlIds )
483 : {
484 : static const char sControlIdBase[] = "control";
485 2 : OUString sControlId = sControlIdBase;
486 :
487 2 : size_t nKnownControlCount = ::std::accumulate( _rAllPagesControlIds.begin(), _rAllPagesControlIds.end(), (size_t)0, AccumulateSize() );
488 2 : sControlId += OUString::number( (sal_Int32)nKnownControlCount + 1 );
489 :
490 : #ifdef DBG_UTIL
491 : // Check if the id is already used. It shouldn't, as we currently have no mechanism for removing entries
492 : // from the map, so the approach used above (take the accumulated map size) should be sufficient. But if
493 : // somebody changes this (e.g. allows removing entries from the map), the assertion below probably will fail.
494 : for ( MapPropertySet2Map::const_iterator outer = _rAllPagesControlIds.begin();
495 : outer != _rAllPagesControlIds.end();
496 : ++outer
497 : )
498 : for ( MapPropertySet2String::const_iterator inner = outer->second.begin();
499 : inner != outer->second.end();
500 : ++inner
501 : )
502 : {
503 : OSL_ENSURE( inner->second != sControlId,
504 : "lcl_findFreeControlId: auto-generated control ID is already used!" );
505 : }
506 : #endif
507 2 : return sControlId;
508 : }
509 : }
510 :
511 4 : bool OFormLayerXMLExport_Impl::checkExamineControl(const Reference< XPropertySet >& _rxObject)
512 : {
513 4 : Reference< XPropertySetInfo > xCurrentInfo = _rxObject->getPropertySetInfo();
514 : OSL_ENSURE(xCurrentInfo.is(), "OFormLayerXMLExport_Impl::checkExamineControl: no property set info");
515 :
516 4 : bool bIsControl = xCurrentInfo->hasPropertyByName( PROPERTY_CLASSID );
517 4 : if (bIsControl)
518 : {
519 : // generate a new control id
520 :
521 : // find a free id
522 2 : OUString sCurrentId = lcl_findFreeControlId( m_aControlIds );
523 : // add it to the map
524 2 : m_aCurrentPageIds->second[_rxObject] = sCurrentId;
525 :
526 : // check if this control has a "LabelControl" property referring another control
527 2 : if ( xCurrentInfo->hasPropertyByName( PROPERTY_CONTROLLABEL ) )
528 : {
529 0 : Reference< XPropertySet > xCurrentReference( _rxObject->getPropertyValue( PROPERTY_CONTROLLABEL ), UNO_QUERY );
530 0 : if (xCurrentReference.is())
531 : {
532 0 : OUString& sReferencedBy = m_aCurrentPageReferring->second[xCurrentReference];
533 0 : if (!sReferencedBy.isEmpty())
534 : // it's not the first _rxObject referring to the xCurrentReference
535 : // -> separate the id
536 0 : sReferencedBy += ",";
537 0 : sReferencedBy += sCurrentId;
538 0 : }
539 : }
540 :
541 : // check if the control needs a number format style
542 2 : if ( xCurrentInfo->hasPropertyByName( PROPERTY_FORMATKEY ) )
543 : {
544 0 : examineControlNumberFormat(_rxObject);
545 : }
546 :
547 : // check if it's a control providing text
548 4 : Reference< XText > xControlText( _rxObject, UNO_QUERY );
549 2 : if ( xControlText.is() )
550 : {
551 0 : m_rContext.GetTextParagraphExport()->collectTextAutoStyles( xControlText );
552 : }
553 :
554 : // check if it is a grid control - in this case, we need special handling for the columns
555 2 : sal_Int16 nControlType = FormComponentType::CONTROL;
556 2 : _rxObject->getPropertyValue( PROPERTY_CLASSID ) >>= nControlType;
557 2 : if ( FormComponentType::GRIDCONTROL == nControlType )
558 : {
559 0 : collectGridColumnStylesAndIds( _rxObject );
560 2 : }
561 : }
562 :
563 4 : return bIsControl;
564 : }
565 :
566 0 : void OFormLayerXMLExport_Impl::collectGridColumnStylesAndIds( const Reference< XPropertySet >& _rxControl )
567 : {
568 : // loop through all columns of the grid
569 : try
570 : {
571 0 : Reference< XIndexAccess > xContainer( _rxControl, UNO_QUERY );
572 : OSL_ENSURE( xContainer.is(), "OFormLayerXMLExport_Impl::collectGridColumnStylesAndIds: grid control not being a container?!" );
573 0 : if ( !xContainer.is() )
574 0 : return;
575 :
576 0 : Reference< XPropertySetInfo > xColumnPropertiesMeta;
577 :
578 0 : sal_Int32 nCount = xContainer->getCount();
579 0 : for ( sal_Int32 i=0; i<nCount; ++i )
580 : {
581 0 : Reference< XPropertySet > xColumnProperties( xContainer->getByIndex( i ), UNO_QUERY );
582 : OSL_ENSURE( xColumnProperties.is(), "OFormLayerXMLExport_Impl::collectGridColumnStylesAndIds: invalid grid column encountered!" );
583 0 : if ( !xColumnProperties.is() )
584 0 : continue;
585 :
586 : // generate a new control id
587 :
588 : // find a free id
589 0 : OUString sCurrentId = lcl_findFreeControlId( m_aControlIds );
590 : // add it to the map
591 0 : m_aCurrentPageIds->second[ xColumnProperties ] = sCurrentId;
592 :
593 : // determine a number style, if needed
594 0 : xColumnPropertiesMeta = xColumnProperties->getPropertySetInfo();
595 : // get the styles of the column
596 0 : ::std::vector< XMLPropertyState > aPropertyStates = m_xStyleExportMapper->Filter( xColumnProperties );
597 :
598 : // care for the number format, additionally
599 0 : OUString sColumnNumberStyle;
600 0 : if ( xColumnPropertiesMeta.is() && xColumnPropertiesMeta->hasPropertyByName( PROPERTY_FORMATKEY ) )
601 0 : sColumnNumberStyle = getImmediateNumberStyle( xColumnProperties );
602 :
603 0 : if ( !sColumnNumberStyle.isEmpty() )
604 : { // the column indeed has a formatting
605 0 : sal_Int32 nStyleMapIndex = m_xStyleExportMapper->getPropertySetMapper()->FindEntryIndex( CTF_FORMS_DATA_STYLE );
606 : // TODO: move this to the ctor
607 : OSL_ENSURE ( -1 != nStyleMapIndex, "OFormLayerXMLExport_Impl::collectGridColumnStylesAndIds: could not obtain the index for our context id!");
608 :
609 0 : XMLPropertyState aNumberStyleState( nStyleMapIndex, makeAny( sColumnNumberStyle ) );
610 0 : aPropertyStates.push_back( aNumberStyleState );
611 : }
612 :
613 : #if OSL_DEBUG_LEVEL > 0
614 : ::std::vector< XMLPropertyState >::const_iterator aHaveALook = aPropertyStates.begin();
615 : for ( ; aHaveALook != aPropertyStates.end(); ++aHaveALook )
616 : {
617 : (void)aHaveALook;
618 : }
619 : #endif
620 :
621 : // determine the column style
622 :
623 0 : if ( !aPropertyStates.empty() )
624 : { // add to the style pool
625 0 : OUString sColumnStyleName = m_rContext.GetAutoStylePool()->Add( XML_STYLE_FAMILY_CONTROL_ID, aPropertyStates );
626 :
627 : OSL_ENSURE( m_aGridColumnStyles.end() == m_aGridColumnStyles.find( xColumnProperties ),
628 : "OFormLayerXMLExport_Impl::collectGridColumnStylesAndIds: already have a style for this column!" );
629 :
630 0 : m_aGridColumnStyles.insert( MapPropertySet2String::value_type( xColumnProperties, sColumnStyleName ) );
631 : }
632 0 : }
633 : }
634 0 : catch( const Exception& )
635 : {
636 : DBG_UNHANDLED_EXCEPTION();
637 : }
638 : }
639 :
640 0 : sal_Int32 OFormLayerXMLExport_Impl::implExamineControlNumberFormat( const Reference< XPropertySet >& _rxObject )
641 : {
642 : // get the format key relative to our own formats supplier
643 0 : sal_Int32 nOwnFormatKey = ensureTranslateFormat( _rxObject );
644 :
645 0 : if ( -1 != nOwnFormatKey )
646 : // tell the exporter that we used this format
647 0 : getControlNumberStyleExport()->SetUsed( nOwnFormatKey );
648 :
649 0 : return nOwnFormatKey;
650 : }
651 :
652 0 : void OFormLayerXMLExport_Impl::examineControlNumberFormat( const Reference< XPropertySet >& _rxControl )
653 : {
654 0 : sal_Int32 nOwnFormatKey = implExamineControlNumberFormat( _rxControl );
655 :
656 0 : if ( -1 == nOwnFormatKey )
657 : // nothing to do, the number format of this control is void
658 0 : return;
659 :
660 : // remember the format key for this control (we'll be asked in getControlNumberStyle for this)
661 : OSL_ENSURE(m_aControlNumberFormats.end() == m_aControlNumberFormats.find(_rxControl),
662 : "OFormLayerXMLExport_Impl::examineControlNumberFormat: already handled this control!");
663 0 : m_aControlNumberFormats[_rxControl] = nOwnFormatKey;
664 : }
665 :
666 0 : sal_Int32 OFormLayerXMLExport_Impl::ensureTranslateFormat(const Reference< XPropertySet >& _rxFormattedControl)
667 : {
668 0 : ensureControlNumberStyleExport();
669 : OSL_ENSURE(m_xControlNumberFormats.is(), "OFormLayerXMLExport_Impl::ensureTranslateFormat: no own formats supplier!");
670 : // (should have been created in ensureControlNumberStyleExport)
671 :
672 0 : sal_Int32 nOwnFormatKey = -1;
673 :
674 : // the format key (relative to the control's supplier)
675 0 : sal_Int32 nControlFormatKey = -1;
676 0 : Any aControlFormatKey = _rxFormattedControl->getPropertyValue(PROPERTY_FORMATKEY);
677 0 : if (aControlFormatKey >>= nControlFormatKey)
678 : {
679 : // the control's number format
680 0 : Reference< XNumberFormatsSupplier > xControlFormatsSupplier;
681 0 : _rxFormattedControl->getPropertyValue(PROPERTY_FORMATSSUPPLIER) >>= xControlFormatsSupplier;
682 0 : Reference< XNumberFormats > xControlFormats;
683 0 : if (xControlFormatsSupplier.is())
684 0 : xControlFormats = xControlFormatsSupplier->getNumberFormats();
685 : OSL_ENSURE(xControlFormats.is(), "OFormLayerXMLExport_Impl::ensureTranslateFormat: formatted control without supplier!");
686 :
687 : // obtain the persistent (does not depend on the formats supplier) representation of the control's format
688 0 : Locale aFormatLocale;
689 0 : OUString sFormatDescription;
690 0 : if (xControlFormats.is())
691 : {
692 0 : Reference< XPropertySet > xControlFormat = xControlFormats->getByKey(nControlFormatKey);
693 :
694 0 : xControlFormat->getPropertyValue(PROPERTY_LOCALE) >>= aFormatLocale;
695 0 : xControlFormat->getPropertyValue(PROPERTY_FORMATSTRING) >>= sFormatDescription;
696 : }
697 :
698 : // check if our own formats collection already knows the format
699 0 : nOwnFormatKey = m_xControlNumberFormats->queryKey(sFormatDescription, aFormatLocale, sal_False);
700 0 : if (-1 == nOwnFormatKey)
701 : { // no, we don't
702 : // -> create a new format
703 0 : nOwnFormatKey = m_xControlNumberFormats->addNew(sFormatDescription, aFormatLocale);
704 : }
705 0 : OSL_ENSURE(-1 != nOwnFormatKey, "OFormLayerXMLExport_Impl::ensureTranslateFormat: could not translate the controls format key!");
706 : }
707 : else
708 : OSL_ENSURE(!aControlFormatKey.hasValue(), "OFormLayerXMLExport_Impl::ensureTranslateFormat: invalid number format property value!");
709 :
710 0 : return nOwnFormatKey;
711 : }
712 :
713 0 : void OFormLayerXMLExport_Impl::ensureControlNumberStyleExport()
714 : {
715 0 : if (!m_pControlNumberStyles)
716 : {
717 : // create our number formats supplier (if necessary)
718 0 : Reference< XNumberFormatsSupplier > xFormatsSupplier;
719 :
720 : OSL_ENSURE(!m_xControlNumberFormats.is(), "OFormLayerXMLExport_Impl::getControlNumberStyleExport: inconsistence!");
721 : // the m_xControlNumberFormats and m_pControlNumberStyles should be maintained together
722 :
723 : try
724 : {
725 : // create it for en-US (does not really matter, as we will specify a locale for every
726 : // concrete language to use)
727 : Locale aLocale ( OUString("en"),
728 : OUString("US"),
729 : OUString()
730 0 : );
731 0 : xFormatsSupplier = NumberFormatsSupplier::createWithLocale( m_rContext.getComponentContext(), aLocale );
732 0 : m_xControlNumberFormats = xFormatsSupplier->getNumberFormats();
733 : }
734 0 : catch(const Exception&)
735 : {
736 : }
737 :
738 : OSL_ENSURE(m_xControlNumberFormats.is(), "OFormLayerXMLExport_Impl::getControlNumberStyleExport: could not obtain my default number formats!");
739 :
740 : // create the exporter
741 0 : m_pControlNumberStyles = new SvXMLNumFmtExport(m_rContext, xFormatsSupplier, getControlNumberStyleNamePrefix());
742 : }
743 0 : }
744 :
745 0 : SvXMLNumFmtExport* OFormLayerXMLExport_Impl::getControlNumberStyleExport()
746 : {
747 0 : ensureControlNumberStyleExport();
748 0 : return m_pControlNumberStyles;
749 : }
750 :
751 0 : void OFormLayerXMLExport_Impl::excludeFromExport( const Reference< XControlModel >& _rxControl )
752 : {
753 0 : Reference< XPropertySet > xProps( _rxControl, UNO_QUERY );
754 : OSL_ENSURE( xProps.is(), "OFormLayerXMLExport_Impl::excludeFromExport: invalid control model!" );
755 : #if OSL_DEBUG_LEVEL > 0
756 : ::std::pair< PropertySetBag::iterator, bool > aPos =
757 : #endif
758 0 : m_aIgnoreList.insert( xProps );
759 0 : OSL_ENSURE( aPos.second, "OFormLayerXMLExport_Impl::excludeFromExport: element already exists in the ignore list!" );
760 0 : }
761 :
762 : } // namespace xmloff
763 :
764 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|