xref: /trunk/main/xmloff/source/draw/ximppage.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_xmloff.hxx"
30 #include <tools/debug.hxx>
31 
32 #include <com/sun/star/geometry/RealPoint2D.hpp>
33 #include <com/sun/star/text/XTextCursor.hpp>
34 #include <com/sun/star/util/DateTime.hpp>
35 #include <cppuhelper/implbase1.hxx>
36 #include "XMLNumberStylesImport.hxx"
37 #include <xmloff/xmlstyle.hxx>
38 #include <xmloff/xmltoken.hxx>
39 #include <xmloff/xmlstyle.hxx>
40 #include "xmloff/xmlnmspe.hxx"
41 #include "ximppage.hxx"
42 #include "ximpshap.hxx"
43 #include "animimp.hxx"
44 #include "XMLStringBufferImportContext.hxx"
45 #include <xmloff/formsimp.hxx>
46 #include <xmloff/xmlictxt.hxx>
47 #include "ximpstyl.hxx"
48 #include <xmloff/prstylei.hxx>
49 #include "PropertySetMerger.hxx"
50 
51 #include "unointerfacetouniqueidentifiermapper.hxx"
52 #include <xmloff/xmluconv.hxx>
53 
54 using ::rtl::OUString;
55 using ::rtl::OUStringBuffer;
56 
57 using namespace ::com::sun::star;
58 using namespace ::xmloff::token;
59 using namespace ::com::sun::star::uno;
60 using namespace ::com::sun::star::lang;
61 using namespace ::com::sun::star::text;
62 using namespace ::com::sun::star::util;
63 using namespace ::com::sun::star::beans;
64 using namespace ::com::sun::star::drawing;
65 using namespace ::com::sun::star::container;
66 using namespace ::com::sun::star::office;
67 using namespace ::com::sun::star::xml::sax;
68 using namespace ::com::sun::star::geometry;
69 
70 
71 //////////////////////////////////////////////////////////////////////////////
72 
73 class DrawAnnotationContext : public SvXMLImportContext
74 {
75 
76 public:
77     DrawAnnotationContext( SvXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLocalName,const Reference< xml::sax::XAttributeList>& xAttrList, const Reference< XAnnotationAccess >& xAnnotationAccess );
78 
79     virtual SvXMLImportContext * CreateChildContext( sal_uInt16 nPrefix, const ::rtl::OUString& rLocalName, const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList>& xAttrList );
80     virtual void EndElement();
81 
82 private:
83     Reference< XAnnotation > mxAnnotation;
84     Reference< XTextCursor > mxCursor;
85 
86     OUStringBuffer maAuthorBuffer;
87     OUStringBuffer maDateBuffer;
88 };
89 
90 DrawAnnotationContext::DrawAnnotationContext( SvXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLocalName,const Reference< xml::sax::XAttributeList>& xAttrList, const Reference< XAnnotationAccess >& xAnnotationAccess )
91 : SvXMLImportContext( rImport, nPrfx, rLocalName )
92 , mxAnnotation( xAnnotationAccess->createAndInsertAnnotation() )
93 {
94     if( mxAnnotation.is() )
95     {
96         sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
97 
98         RealPoint2D aPosition;
99         RealSize2D aSize;
100 
101         for(sal_Int16 i=0; i < nAttrCount; i++)
102         {
103             OUString sValue( xAttrList->getValueByIndex( i ) );
104             OUString sAttrName( xAttrList->getNameByIndex( i ) );
105             OUString aLocalName;
106             switch( GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName ) )
107             {
108             case XML_NAMESPACE_SVG:
109                 if( IsXMLToken( aLocalName, XML_X ) )
110                 {
111                     sal_Int32 x;
112                     GetImport().GetMM100UnitConverter().convertMeasure(x, sValue);
113                     aPosition.X = static_cast<double>(x) / 100.0;
114                 }
115                 else if( IsXMLToken( aLocalName, XML_Y ) )
116                 {
117                     sal_Int32 y;
118                     GetImport().GetMM100UnitConverter().convertMeasure(y, sValue);
119                     aPosition.Y = static_cast<double>(y) / 100.0;
120                 }
121                 else if( IsXMLToken( aLocalName, XML_WIDTH ) )
122                 {
123                     sal_Int32 w;
124                     GetImport().GetMM100UnitConverter().convertMeasure(w, sValue);
125                     aSize.Width = static_cast<double>(w) / 100.0;
126                 }
127                 else if( IsXMLToken( aLocalName, XML_HEIGHT ) )
128                 {
129                     sal_Int32 h;
130                     GetImport().GetMM100UnitConverter().convertMeasure(h, sValue);
131                     aSize.Height = static_cast<double>(h) / 100.0;
132                 }
133                 break;
134             default:
135                 break;
136             }
137         }
138 
139         mxAnnotation->setPosition( aPosition );
140         mxAnnotation->setSize( aSize );
141     }
142 }
143 
144 SvXMLImportContext * DrawAnnotationContext::CreateChildContext( sal_uInt16 nPrefix, const OUString& rLocalName, const Reference< XAttributeList >& xAttrList )
145 {
146     SvXMLImportContext * pContext = NULL;
147 
148     if( mxAnnotation.is() )
149     {
150         if( XML_NAMESPACE_DC == nPrefix )
151         {
152             if( IsXMLToken( rLocalName, XML_CREATOR ) )
153                 pContext = new XMLStringBufferImportContext(GetImport(), nPrefix, rLocalName, maAuthorBuffer);
154             else if( IsXMLToken( rLocalName, XML_DATE ) )
155                 pContext = new XMLStringBufferImportContext(GetImport(), nPrefix, rLocalName, maDateBuffer);
156         }
157         else
158         {
159             // create text cursor on demand
160             if( !mxCursor.is() )
161             {
162                 uno::Reference< text::XText > xText( mxAnnotation->getTextRange() );
163                 if( xText.is() )
164                 {
165                     UniReference < XMLTextImportHelper > xTxtImport = GetImport().GetTextImport();
166                     mxCursor = xText->createTextCursor();
167                     if( mxCursor.is() )
168                         xTxtImport->SetCursor( mxCursor );
169                 }
170             }
171 
172             // if we have a text cursor, lets  try to import some text
173             if( mxCursor.is() )
174             {
175                 pContext = GetImport().GetTextImport()->CreateTextChildContext( GetImport(), nPrefix, rLocalName, xAttrList );
176             }
177         }
178     }
179 
180     // call parent for content
181     if(!pContext)
182         pContext = SvXMLImportContext::CreateChildContext( nPrefix, rLocalName, xAttrList );
183 
184     return pContext;
185 }
186 
187 void DrawAnnotationContext::EndElement()
188 {
189     if(mxCursor.is())
190     {
191         // delete addition newline
192         const OUString aEmpty;
193         mxCursor->gotoEnd( sal_False );
194         mxCursor->goLeft( 1, sal_True );
195         mxCursor->setString( aEmpty );
196 
197         // reset cursor
198         GetImport().GetTextImport()->ResetCursor();
199     }
200 
201     if( mxAnnotation.is() )
202     {
203         mxAnnotation->setAuthor( maAuthorBuffer.makeStringAndClear() );
204 
205         DateTime aDateTime;
206         if(SvXMLUnitConverter::convertDateTime(aDateTime,  maDateBuffer.makeStringAndClear()))
207             mxAnnotation->setDateTime(aDateTime);
208     }
209 }
210 
211 //////////////////////////////////////////////////////////////////////////////
212 
213 TYPEINIT1( SdXMLGenericPageContext, SvXMLImportContext );
214 
215 SdXMLGenericPageContext::SdXMLGenericPageContext(
216     SvXMLImport& rImport,
217     sal_uInt16 nPrfx, const OUString& rLocalName,
218     const Reference< xml::sax::XAttributeList>& xAttrList,
219     Reference< drawing::XShapes >& rShapes)
220 : SvXMLImportContext( rImport, nPrfx, rLocalName )
221 , mxShapes( rShapes )
222 , mxAnnotationAccess( rShapes, UNO_QUERY )
223 {
224     sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
225 
226     for(sal_Int16 i=0; i < nAttrCount; i++)
227     {
228         OUString sAttrName = xAttrList->getNameByIndex( i );
229         OUString aLocalName;
230         sal_uInt16 nPrefix = GetSdImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
231         if( (nPrefix == XML_NAMESPACE_DRAW) && IsXMLToken( aLocalName, XML_NAV_ORDER ) )
232         {
233             msNavOrder = xAttrList->getValueByIndex( i );
234             break;
235         }
236     }
237 }
238 
239 //////////////////////////////////////////////////////////////////////////////
240 
241 SdXMLGenericPageContext::~SdXMLGenericPageContext()
242 {
243 }
244 
245 //////////////////////////////////////////////////////////////////////////////
246 
247 void SdXMLGenericPageContext::StartElement( const Reference< ::com::sun::star::xml::sax::XAttributeList >& )
248 {
249     GetImport().GetShapeImport()->pushGroupForSorting( mxShapes );
250 
251     if( GetImport().IsFormsSupported() )
252         GetImport().GetFormImport()->startPage( Reference< drawing::XDrawPage >::query( mxShapes ) );
253 }
254 
255 //////////////////////////////////////////////////////////////////////////////
256 
257 SvXMLImportContext* SdXMLGenericPageContext::CreateChildContext( sal_uInt16 nPrefix,
258     const OUString& rLocalName,
259     const Reference< xml::sax::XAttributeList>& xAttrList )
260 {
261     SvXMLImportContext* pContext = 0L;
262 
263     if( nPrefix == XML_NAMESPACE_PRESENTATION && IsXMLToken( rLocalName, XML_ANIMATIONS ) )
264     {
265         pContext = new XMLAnimationsContext( GetImport(), nPrefix, rLocalName, xAttrList );
266     }
267     else if( nPrefix == XML_NAMESPACE_OFFICE && IsXMLToken( rLocalName, XML_FORMS ) )
268     {
269         if( GetImport().IsFormsSupported() )
270             pContext = GetImport().GetFormImport()->createOfficeFormsContext( GetImport(), nPrefix, rLocalName );
271     }
272     else if( ((nPrefix == XML_NAMESPACE_OFFICE) || (nPrefix == XML_NAMESPACE_OFFICE_EXT)) && IsXMLToken( rLocalName, XML_ANNOTATION ) )
273     {
274         if( mxAnnotationAccess.is() )
275             pContext = new DrawAnnotationContext( GetImport(), nPrefix, rLocalName, xAttrList, mxAnnotationAccess );
276     }
277     else
278     {
279         // call GroupChildContext function at common ShapeImport
280         pContext = GetImport().GetShapeImport()->CreateGroupChildContext(
281             GetImport(), nPrefix, rLocalName, xAttrList, mxShapes);
282     }
283 
284     // call parent when no own context was created
285     if(!pContext)
286         pContext = SvXMLImportContext::CreateChildContext(nPrefix, rLocalName, xAttrList);
287 
288     return pContext;
289 }
290 
291 //////////////////////////////////////////////////////////////////////////////
292 
293 void SdXMLGenericPageContext::EndElement()
294 {
295     GetImport().GetShapeImport()->popGroupAndSort();
296 
297     if( GetImport().IsFormsSupported() )
298         GetImport().GetFormImport()->endPage();
299 
300     if( maUseHeaderDeclName.getLength() || maUseFooterDeclName.getLength() || maUseDateTimeDeclName.getLength() )
301     {
302         try
303         {
304             Reference <beans::XPropertySet> xSet(mxShapes, uno::UNO_QUERY_THROW );
305             Reference< beans::XPropertySetInfo > xInfo( xSet->getPropertySetInfo() );
306 
307             if( maUseHeaderDeclName.getLength() )
308             {
309                 const OUString aStrHeaderTextProp( RTL_CONSTASCII_USTRINGPARAM( "HeaderText" ) );
310                 if( xInfo->hasPropertyByName( aStrHeaderTextProp ) )
311                     xSet->setPropertyValue( aStrHeaderTextProp,
312                                             makeAny( GetSdImport().GetHeaderDecl( maUseHeaderDeclName ) ) );
313             }
314 
315             if( maUseFooterDeclName.getLength() )
316             {
317                 const OUString aStrFooterTextProp( RTL_CONSTASCII_USTRINGPARAM( "FooterText" ) );
318                 if( xInfo->hasPropertyByName( aStrFooterTextProp ) )
319                     xSet->setPropertyValue( aStrFooterTextProp,
320                                         makeAny( GetSdImport().GetFooterDecl( maUseFooterDeclName ) ) );
321             }
322 
323             if( maUseDateTimeDeclName.getLength() )
324             {
325                 const OUString aStrDateTimeTextProp( RTL_CONSTASCII_USTRINGPARAM( "DateTimeText" ) );
326                 if( xInfo->hasPropertyByName( aStrDateTimeTextProp ) )
327                 {
328                     sal_Bool bFixed;
329                     OUString aDateTimeFormat;
330                     const OUString aText( GetSdImport().GetDateTimeDecl( maUseDateTimeDeclName, bFixed, aDateTimeFormat ) );
331 
332                     xSet->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("IsDateTimeFixed") ),
333                                         makeAny( bFixed ) );
334 
335                     if( bFixed )
336                     {
337                         xSet->setPropertyValue( aStrDateTimeTextProp, makeAny( aText ) );
338                     }
339                     else if( aDateTimeFormat.getLength() )
340                     {
341                         const SdXMLStylesContext* pStyles = dynamic_cast< const SdXMLStylesContext* >( GetSdImport().GetShapeImport()->GetStylesContext() );
342                         if( !pStyles )
343                             pStyles = dynamic_cast< const SdXMLStylesContext* >( GetSdImport().GetShapeImport()->GetAutoStylesContext() );
344 
345                         if( pStyles )
346                         {
347                             const SdXMLNumberFormatImportContext* pSdNumStyle =
348                                 dynamic_cast< const SdXMLNumberFormatImportContext* >( pStyles->FindStyleChildContext( XML_STYLE_FAMILY_DATA_STYLE, aDateTimeFormat, sal_True ) );
349 
350                             if( pSdNumStyle )
351                             {
352                                 xSet->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("DateTimeFormat") ),
353                                                                     makeAny( pSdNumStyle->GetDrawKey() ) );
354                             }
355                         }
356                     }
357                 }
358             }
359         }
360         catch( uno::Exception& e )
361         {
362             (void)e;
363             DBG_ERROR("xmloff::SdXMLGenericPageContext::EndElement(), unexpected exception cought!");
364         }
365     }
366 
367     SetNavigationOrder();
368 }
369 
370 void SdXMLGenericPageContext::SetStyle( rtl::OUString& rStyleName )
371 {
372     // set PageProperties?
373     if(rStyleName.getLength())
374     {
375         try
376         {
377             const SvXMLImportContext* pContext = GetSdImport().GetShapeImport()->GetAutoStylesContext();
378 
379             if( pContext && pContext->ISA( SvXMLStyleContext ) )
380             {
381                 const SdXMLStylesContext* pStyles = (SdXMLStylesContext*)pContext;
382                 if(pStyles)
383                 {
384                     const SvXMLStyleContext* pStyle = pStyles->FindStyleChildContext(
385                         XML_STYLE_FAMILY_SD_DRAWINGPAGE_ID, rStyleName);
386 
387                     if(pStyle && pStyle->ISA(XMLPropStyleContext))
388                     {
389                         XMLPropStyleContext* pPropStyle = (XMLPropStyleContext*)pStyle;
390 
391                         Reference <beans::XPropertySet> xPropSet1(mxShapes, uno::UNO_QUERY);
392                         if(xPropSet1.is())
393                         {
394                             Reference< beans::XPropertySet > xPropSet( xPropSet1 );
395                             Reference< beans::XPropertySet > xBackgroundSet;
396 
397                             const OUString aBackground(RTL_CONSTASCII_USTRINGPARAM("Background"));
398                             if( xPropSet1->getPropertySetInfo()->hasPropertyByName( aBackground ) )
399                             {
400                                 Reference< beans::XPropertySetInfo > xInfo( xPropSet1->getPropertySetInfo() );
401                                 if( xInfo.is() && xInfo->hasPropertyByName( aBackground ) )
402                                 {
403                                     Reference< lang::XMultiServiceFactory > xServiceFact(GetSdImport().GetModel(), uno::UNO_QUERY);
404                                     if(xServiceFact.is())
405                                     {
406                                         xBackgroundSet = Reference< beans::XPropertySet >::query(
407                                             xServiceFact->createInstance(
408                                             OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.Background"))));
409                                     }
410                                 }
411 
412                                 if( xBackgroundSet.is() )
413                                     xPropSet = PropertySetMerger_CreateInstance( xPropSet1, xBackgroundSet );
414                             }
415 
416                             if(xPropSet.is())
417                             {
418                                 pPropStyle->FillPropertySet(xPropSet);
419 
420                                 if( xBackgroundSet.is() )
421                                     xPropSet1->setPropertyValue( aBackground, uno::makeAny( xBackgroundSet ) );
422                             }
423                         }
424                     }
425                 }
426             }
427         }
428         catch( uno::Exception )
429         {
430             DBG_ERROR( "SdXMLGenericPageContext::SetStyle(): uno::Exception catched!" );
431         }
432     }
433 }
434 
435 void SdXMLGenericPageContext::SetLayout()
436 {
437     // set PresentationPageLayout?
438     if(GetSdImport().IsImpress() && maPageLayoutName.getLength())
439     {
440         sal_Int32 nType = -1;
441 
442         const SvXMLImportContext* pContext = GetSdImport().GetShapeImport()->GetStylesContext();
443 
444         if( pContext && pContext->ISA( SvXMLStyleContext ) )
445         {
446             const SdXMLStylesContext* pStyles = (SdXMLStylesContext*)pContext;
447             if(pStyles)
448             {
449                 const SvXMLStyleContext* pStyle = pStyles->FindStyleChildContext( XML_STYLE_FAMILY_SD_PRESENTATIONPAGELAYOUT_ID, maPageLayoutName);
450 
451                 if(pStyle && pStyle->ISA(SdXMLPresentationPageLayoutContext))
452                 {
453                     SdXMLPresentationPageLayoutContext* pLayout = (SdXMLPresentationPageLayoutContext*)pStyle;
454                     nType = pLayout->GetTypeId();
455                 }
456             }
457 
458         }
459         if( -1 == nType )
460         {
461             Reference< container::XNameAccess > xPageLayouts( GetSdImport().getPageLayouts() );
462             if( xPageLayouts.is() )
463             {
464                 if( xPageLayouts->hasByName( maPageLayoutName ) )
465                     xPageLayouts->getByName( maPageLayoutName ) >>= nType;
466             }
467 
468         }
469 
470         if( -1 != nType )
471         {
472             Reference <beans::XPropertySet> xPropSet(mxShapes, uno::UNO_QUERY);
473             if(xPropSet.is())
474             {
475                 OUString aPropName(RTL_CONSTASCII_USTRINGPARAM("Layout"));
476                 Reference< beans::XPropertySetInfo > xInfo( xPropSet->getPropertySetInfo() );
477                 if( xInfo.is() && xInfo->hasPropertyByName( aPropName ) )
478                     xPropSet->setPropertyValue(aPropName, uno::makeAny( (sal_Int16)nType ) );
479             }
480         }
481     }
482 }
483 
484 void SdXMLGenericPageContext::DeleteAllShapes()
485 {
486     // now delete all up-to-now contained shapes; they have been created
487     // when setting the presentation page layout.
488     while(mxShapes->getCount())
489     {
490         Reference< drawing::XShape > xShape;
491         uno::Any aAny(mxShapes->getByIndex(0L));
492 
493         aAny >>= xShape;
494 
495         if(xShape.is())
496         {
497             mxShapes->remove(xShape);
498         }
499     }
500 }
501 
502 void SdXMLGenericPageContext::SetPageMaster( OUString& rsPageMasterName )
503 {
504     if( GetSdImport().GetShapeImport()->GetStylesContext() )
505     {
506         // look for PageMaster with this name
507 
508         // #80012# GetStylesContext() replaced with GetAutoStylesContext()
509         const SvXMLStylesContext* pAutoStyles = GetSdImport().GetShapeImport()->GetAutoStylesContext();
510 
511         const SvXMLStyleContext* pStyle = pAutoStyles ? pAutoStyles->FindStyleChildContext(XML_STYLE_FAMILY_SD_PAGEMASTERCONEXT_ID, rsPageMasterName) : NULL;
512 
513         if(pStyle && pStyle->ISA(SdXMLPageMasterContext))
514         {
515             const SdXMLPageMasterContext* pPageMaster = (SdXMLPageMasterContext*)pStyle;
516             const SdXMLPageMasterStyleContext* pPageMasterContext = pPageMaster->GetPageMasterStyle();
517 
518             if(pPageMasterContext)
519             {
520                 Reference< drawing::XDrawPage > xMasterPage(GetLocalShapesContext(), uno::UNO_QUERY);
521                 if(xMasterPage.is())
522                 {
523                     // set sizes for this masterpage
524                     Reference <beans::XPropertySet> xPropSet(xMasterPage, uno::UNO_QUERY);
525                     if(xPropSet.is())
526                     {
527                         uno::Any aAny;
528 
529                         aAny <<= pPageMasterContext->GetBorderBottom();
530                         xPropSet->setPropertyValue(
531                             OUString(RTL_CONSTASCII_USTRINGPARAM("BorderBottom")), aAny);
532 
533                         aAny <<= pPageMasterContext->GetBorderLeft();
534                         xPropSet->setPropertyValue(
535                             OUString(RTL_CONSTASCII_USTRINGPARAM("BorderLeft")), aAny);
536 
537                         aAny <<= pPageMasterContext->GetBorderRight();
538                         xPropSet->setPropertyValue(
539                             OUString(RTL_CONSTASCII_USTRINGPARAM("BorderRight")), aAny);
540 
541                         aAny <<= pPageMasterContext->GetBorderTop();
542                         xPropSet->setPropertyValue(
543                             OUString(RTL_CONSTASCII_USTRINGPARAM("BorderTop")), aAny);
544 
545                         aAny <<= pPageMasterContext->GetWidth();
546                         xPropSet->setPropertyValue(
547                             OUString(RTL_CONSTASCII_USTRINGPARAM("Width")), aAny);
548 
549                         aAny <<= pPageMasterContext->GetHeight();
550                         xPropSet->setPropertyValue(
551                             OUString(RTL_CONSTASCII_USTRINGPARAM("Height")), aAny);
552 
553                         aAny <<= pPageMasterContext->GetOrientation();
554                         xPropSet->setPropertyValue(
555                             OUString(RTL_CONSTASCII_USTRINGPARAM("Orientation")), aAny);
556                     }
557                 }
558             }
559         }
560 
561     }
562 }
563 
564 class NavigationOrderAccess : public ::cppu::WeakImplHelper1< XIndexAccess >
565 {
566 public:
567     NavigationOrderAccess( std::vector< Reference< XShape > >& rShapes );
568 
569     // XIndexAccess
570     virtual sal_Int32 SAL_CALL getCount(  ) throw (RuntimeException);
571     virtual Any SAL_CALL getByIndex( sal_Int32 Index ) throw (IndexOutOfBoundsException, WrappedTargetException, RuntimeException);
572 
573     // XElementAccess
574     virtual Type SAL_CALL getElementType(  ) throw (RuntimeException);
575     virtual sal_Bool SAL_CALL hasElements(  ) throw (RuntimeException);
576 
577 private:
578     std::vector< Reference< XShape > > maShapes;
579 };
580 
581 NavigationOrderAccess::NavigationOrderAccess( std::vector< Reference< XShape > >& rShapes )
582 {
583     maShapes.swap( rShapes );
584 }
585 
586 // XIndexAccess
587 sal_Int32 SAL_CALL NavigationOrderAccess::getCount(  ) throw (RuntimeException)
588 {
589     return static_cast< sal_Int32 >( maShapes.size() );
590 }
591 
592 Any SAL_CALL NavigationOrderAccess::getByIndex( sal_Int32 Index ) throw (IndexOutOfBoundsException, WrappedTargetException, RuntimeException)
593 {
594     if( (Index < 0) || (Index > getCount()) )
595         throw IndexOutOfBoundsException();
596 
597     return Any( maShapes[Index] );
598 }
599 
600 // XElementAccess
601 Type SAL_CALL NavigationOrderAccess::getElementType(  ) throw (RuntimeException)
602 {
603     return XShape::static_type();
604 }
605 
606 sal_Bool SAL_CALL NavigationOrderAccess::hasElements(  ) throw (RuntimeException)
607 {
608     return maShapes.empty() ? sal_False : sal_True;
609 }
610 
611 void SdXMLGenericPageContext::SetNavigationOrder()
612 {
613     if( msNavOrder.getLength() != 0 ) try
614     {
615         sal_uInt32 nIndex;
616         const sal_uInt32 nCount = static_cast< sal_uInt32 >( mxShapes->getCount() );
617         std::vector< Reference< XShape > > aShapes( nCount );
618 
619         ::comphelper::UnoInterfaceToUniqueIdentifierMapper& rIdMapper = GetSdImport().getInterfaceToIdentifierMapper();
620         SvXMLTokenEnumerator aEnumerator( msNavOrder );
621         OUString sId;
622         for( nIndex = 0; nIndex < nCount; ++nIndex )
623         {
624             if( !aEnumerator.getNextToken(sId) )
625                 break;
626 
627             aShapes[nIndex] = Reference< XShape >( rIdMapper.getReference( sId ), UNO_QUERY );
628         }
629 
630         for( nIndex = 0; nIndex < nCount; ++nIndex )
631         {
632             if( !aShapes[nIndex].is() )
633             {
634                 DBG_ERROR("xmloff::SdXMLGenericPageContext::SetNavigationOrder(), draw:nav-order attribute incomplete!");
635                 // todo: warning?
636                 return;
637             }
638         }
639 
640         Reference< XPropertySet > xSet( mxShapes, UNO_QUERY_THROW );
641         xSet->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "NavigationOrder" ) ), Any( Reference< XIndexAccess >( new NavigationOrderAccess( aShapes ) ) ) );
642     }
643     catch( uno::Exception& )
644     {
645         DBG_ERROR("xmloff::SdXMLGenericPageContext::SetNavigationOrder(), unexpected exception cought while importing shape navigation order!");
646     }
647 }
648