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