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