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_chart2.hxx"
30 
31 #include "ObjectIdentifier.hxx"
32 #include "macros.hxx"
33 #include "TitleHelper.hxx"
34 #include "ChartModelHelper.hxx"
35 #include "AxisHelper.hxx"
36 #include "servicenames_charttypes.hxx"
37 #include "DiagramHelper.hxx"
38 #include "AxisIndexDefines.hxx"
39 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
40 #include <com/sun/star/chart2/XChartDocument.hpp>
41 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
42 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
43 #include <com/sun/star/chart2/XAxis.hpp>
44 #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
45 
46 // header for define DBG_ASSERT
47 #include <tools/debug.hxx>
48 #include <comphelper/InlineContainer.hxx>
49 
50 #include <rtl/ustrbuf.hxx>
51 
52 //.............................................................................
53 namespace chart
54 {
55 //.............................................................................
56 using namespace ::com::sun::star;
57 using namespace ::com::sun::star::chart2;
58 
59 using rtl::OUString;
60 using rtl::OUStringBuffer;
61 using ::com::sun::star::uno::Reference;
62 using ::com::sun::star::uno::Any;
63 
64 static OUString m_aMultiClick( C2U("MultiClick") );
65 static OUString m_aDragMethodEquals( C2U("DragMethod=") );
66 static OUString m_aDragParameterEquals( C2U("DragParameter=") );
67 static OUString m_aProtocol( C2U("CID/") );
68 static OUString m_aEmptyString;
69 static OUString m_aPieSegmentDragMethodServiceName( C2U("PieSegmentDraging") );
70 
71 namespace
72 {
73 
74 OUString lcl_createClassificationStringForType( ObjectType eObjectType
75             , const OUString& rDragMethodServiceName
76             , const OUString& rDragParameterString
77             )
78 {
79     OUStringBuffer aRet;
80     switch( eObjectType )
81     {
82         //these object types are all selected only after their parents was selected before
83         case OBJECTTYPE_LEGEND_ENTRY: //parent is intended to be OBJECTTYPE_LEGEND
84         case OBJECTTYPE_DATA_POINT: //parent is intended to be OBJECTTYPE_DATA_SERIES
85         case OBJECTTYPE_DATA_LABEL: //parent is intended to be OBJECTTYPE_DATA_LABELS
86         case OBJECTTYPE_DATA_ERRORS_X: //parent is intended to be OBJECTTYPE_DATA_ERRORS
87         case OBJECTTYPE_DATA_ERRORS_Y: //parent is intended to be OBJECTTYPE_DATA_ERRORS
88         case OBJECTTYPE_DATA_ERRORS_Z: //parent is intended to be OBJECTTYPE_DATA_ERRORS
89             aRet=m_aMultiClick;
90         default:
91             ;//empty string
92     }
93     if( rDragMethodServiceName.getLength() )
94     {
95         if( aRet.getLength() )
96             aRet.appendAscii(":");
97         aRet.append( m_aDragMethodEquals );
98         aRet.append( rDragMethodServiceName );
99 
100         if( rDragParameterString.getLength() )
101         {
102             if( aRet.getLength() )
103                 aRet.appendAscii(":");
104             aRet.append( m_aDragParameterEquals );
105             aRet.append( rDragParameterString );
106         }
107     }
108     return aRet.makeStringAndClear();
109 }
110 
111 typedef ::comphelper::MakeMap< TitleHelper::eTitleType, OUString > tTitleMap;
112 const tTitleMap& lcl_getTitleMap()
113 {
114     //maps the title type to the ParentParticle for that title
115     static tTitleMap m_aTitleMap = tTitleMap
116         ( TitleHelper::MAIN_TITLE, C2U("") )
117         ( TitleHelper::SUB_TITLE, C2U("D=0") )
118         ( TitleHelper::X_AXIS_TITLE, C2U("D=0:CS=0:Axis=0,0") )
119         ( TitleHelper::Y_AXIS_TITLE, C2U("D=0:CS=0:Axis=1,0") )
120         ( TitleHelper::Z_AXIS_TITLE, C2U("D=0:CS=0:Axis=2,0") )
121         ( TitleHelper::SECONDARY_X_AXIS_TITLE, C2U("D=0:CS=0:Axis=0,1") )
122         ( TitleHelper::SECONDARY_Y_AXIS_TITLE, C2U("D=0:CS=0:Axis=1,1") )
123         ;
124     return m_aTitleMap;
125 }
126 
127 OUString lcl_getTitleParentParticle( TitleHelper::eTitleType aTitleType )
128 {
129     OUString aRet;
130 
131     const tTitleMap& rMap = lcl_getTitleMap();
132     tTitleMap::const_iterator aIt( rMap.find( aTitleType ) );
133     if( aIt != rMap.end())
134         aRet = (*aIt).second;
135 
136     return aRet;
137 }
138 
139 Reference<XChartType> lcl_getFirstStockChartType( const Reference< frame::XModel >& xChartModel )
140 {
141     Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) );
142     if(!xDiagram.is())
143         return 0;
144 
145     //iterate through all coordinate systems
146     Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
147     if( !xCooSysContainer.is())
148         return 0;
149 
150     uno::Sequence< Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
151     for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS )
152     {
153         //iterate through all chart types in the current coordinate system
154         Reference< XChartTypeContainer > xChartTypeContainer( aCooSysList[nCS], uno::UNO_QUERY );
155         if( !xChartTypeContainer.is() )
156             continue;
157 
158         uno::Sequence< Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
159         for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT )
160         {
161             Reference< XChartType > xChartType( aChartTypeList[nT] );
162             if(!xChartType.is())
163                 continue;
164             OUString aChartType = xChartType->getChartType();
165             if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK) )
166                 return xChartType;
167         }
168     }
169     return 0;
170 }
171 
172 OUString lcl_getIndexStringAfterString( const OUString& rString, const OUString& rSearchString )
173 {
174     OUStringBuffer aRet;
175 
176     sal_Int32 nIndexStart = rString.lastIndexOf( rSearchString );
177     if( nIndexStart != -1 )
178     {
179         nIndexStart += rSearchString.getLength();
180         sal_Int32 nIndexEnd = rString.getLength();
181         sal_Int32 nNextColon = rString.indexOf( ':', nIndexStart );
182         if( nNextColon != -1 )
183             nIndexEnd = nNextColon;
184         aRet = rString.copy(nIndexStart,nIndexEnd-nIndexStart);
185     }
186 
187     return aRet.makeStringAndClear();
188 }
189 
190 sal_Int32 lcl_StringToIndex( const OUString& rIndexString )
191 {
192     sal_Int32 nRet = -1;
193     if( rIndexString.getLength() )
194     {
195         nRet = rIndexString.toInt32();
196         if( nRet < -1 )
197             nRet = -1;
198     }
199     return nRet;
200 }
201 
202 void lcl_parseCooSysIndices( sal_Int32& rnDiagram, sal_Int32& rnCooSys, const OUString& rString )
203 {
204     rnDiagram = lcl_StringToIndex( lcl_getIndexStringAfterString( rString, C2U("D=") ) );
205     rnCooSys = lcl_StringToIndex( lcl_getIndexStringAfterString( rString, C2U("CS=") ) );
206 }
207 
208 void lcl_parseAxisIndices( sal_Int32& rnDimensionIndex, sal_Int32& rnAxisIndex, const OUString& rString )
209 {
210     OUString aAxisIndexString = lcl_getIndexStringAfterString( rString, C2U(":Axis=") );
211     sal_Int32 nCharacterIndex=0;
212     rnDimensionIndex = lcl_StringToIndex( aAxisIndexString.getToken( 0, ',', nCharacterIndex ) );
213     rnAxisIndex = lcl_StringToIndex( aAxisIndexString.getToken( 0, ',', nCharacterIndex ) );
214 }
215 
216 void lcl_parseGridIndices( sal_Int32& rnSubGridIndex, const OUString& rString )
217 {
218     rnSubGridIndex = -1;
219     rnSubGridIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rString, C2U(":SubGrid=") ) );
220 }
221 
222 void lcl_parseSeriesIndices( sal_Int32& rnChartTypeIndex, sal_Int32& rnSeriesIndex, sal_Int32& rnPointIndex, const OUString& rString )
223 {
224     rnChartTypeIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rString, C2U("CT=") ) );
225     rnSeriesIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rString, C2U("Series=") ) );
226     rnPointIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rString, C2U("Point=") ) );
227 }
228 
229 void lcl_getDiagramAndCooSys( const OUString& rObjectCID
230                 , const Reference< frame::XModel >& xChartModel
231                 , Reference< XDiagram >& xDiagram
232                 , Reference< XCoordinateSystem >& xCooSys )
233 {
234     sal_Int32 nDiagramIndex = -1;
235     sal_Int32 nCooSysIndex = -1;
236     lcl_parseCooSysIndices( nDiagramIndex, nCooSysIndex, rObjectCID );
237     xDiagram = ChartModelHelper::findDiagram( xChartModel );//todo use nDiagramIndex when more than one diagram is possible in future
238     if( !xDiagram.is() )
239         return;
240 
241     if( nCooSysIndex > -1 )
242     {
243         Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
244         if( xCooSysContainer.is() )
245         {
246             uno::Sequence< Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
247             if( nCooSysIndex < aCooSysList.getLength() )
248                 xCooSys = aCooSysList[nCooSysIndex];
249         }
250     }
251 }
252 
253 } //anonymous namespace
254 
255 ObjectIdentifier::ObjectIdentifier()
256     :m_aObjectCID( OUString() )
257     ,m_xAdditionalShape( 0 )
258 {
259 }
260 
261 ObjectIdentifier::ObjectIdentifier( const OUString& rObjectCID )
262     :m_aObjectCID( rObjectCID )
263     ,m_xAdditionalShape( 0 )
264 {
265 }
266 
267 ObjectIdentifier::ObjectIdentifier( const Reference< drawing::XShape >& rxShape )
268     :m_aObjectCID( OUString() )
269     ,m_xAdditionalShape( rxShape )
270 {
271 }
272 
273 ObjectIdentifier::ObjectIdentifier( const Any& rAny )
274     :m_aObjectCID( OUString() )
275     ,m_xAdditionalShape( 0 )
276 {
277     const uno::Type& rType = rAny.getValueType();
278     if ( rType == ::getCppuType( static_cast< const OUString* >( 0 ) ) )
279     {
280         rAny >>= m_aObjectCID;
281     }
282     else if ( rType == ::getCppuType( static_cast< const Reference< drawing::XShape >* >( 0 ) ) )
283     {
284         rAny >>= m_xAdditionalShape;
285     }
286 }
287 
288 ObjectIdentifier::~ObjectIdentifier()
289 {
290 }
291 
292 ObjectIdentifier::ObjectIdentifier( const ObjectIdentifier& rOID )
293     :m_aObjectCID( rOID.m_aObjectCID )
294     ,m_xAdditionalShape( rOID.m_xAdditionalShape )
295 {
296 
297 }
298 
299 ObjectIdentifier& ObjectIdentifier::operator=( const ObjectIdentifier& rOID )
300 {
301     m_aObjectCID = rOID.m_aObjectCID;
302     m_xAdditionalShape = rOID.m_xAdditionalShape;
303     return *this;
304 }
305 
306 bool ObjectIdentifier::operator==( const ObjectIdentifier& rOID ) const
307 {
308     if ( areIdenticalObjects( m_aObjectCID, rOID.m_aObjectCID ) &&
309          ( m_xAdditionalShape == rOID.m_xAdditionalShape ) )
310     {
311         return true;
312     }
313     return false;
314 }
315 
316 bool ObjectIdentifier::operator!=( const ObjectIdentifier& rOID ) const
317 {
318     return !operator==( rOID );
319 }
320 
321 bool ObjectIdentifier::operator<( const ObjectIdentifier& rOID ) const
322 {
323     bool bReturn = false;
324     if ( m_aObjectCID.getLength() && rOID.m_aObjectCID.getLength() )
325     {
326         bReturn = ( m_aObjectCID.compareTo( rOID.m_aObjectCID ) < 0 );
327     }
328     else if ( m_aObjectCID.getLength() )
329     {
330         bReturn = true;
331     }
332     else if ( rOID.m_aObjectCID.getLength() )
333     {
334         bReturn = false;
335     }
336     else if ( m_xAdditionalShape.is() && rOID.m_xAdditionalShape.is() )
337     {
338         bReturn = ( m_xAdditionalShape < rOID.m_xAdditionalShape );
339     }
340     return bReturn;
341 }
342 
343 OUString ObjectIdentifier::createClassifiedIdentifierForObject(
344           const Reference< uno::XInterface >& xObject
345         , const Reference< frame::XModel >& xChartModel )
346 {
347     OUString aRet;
348 
349     enum ObjectType eObjectType = OBJECTTYPE_UNKNOWN;
350     OUString aObjectID;
351     OUString aParentParticle;
352     OUString aDragMethodServiceName;
353     OUString aDragParameterString;
354 
355 
356     try
357     {
358         //title
359         Reference< XTitle > xTitle( xObject, uno::UNO_QUERY );
360         if( xTitle.is() )
361         {
362             TitleHelper::eTitleType aTitleType;
363             if( TitleHelper::getTitleType( aTitleType, xTitle, xChartModel ) )
364             {
365                 eObjectType = OBJECTTYPE_TITLE;
366                 aParentParticle = lcl_getTitleParentParticle( aTitleType );
367                 aRet = ObjectIdentifier::createClassifiedIdentifierWithParent(
368                     eObjectType, aObjectID, aParentParticle, aDragMethodServiceName, aDragParameterString );
369             }
370             return aRet;
371 
372         }
373 
374         //axis
375         Reference< XAxis > xAxis( xObject, uno::UNO_QUERY );
376         if( xAxis.is() )
377         {
378             Reference< XCoordinateSystem > xCooSys( AxisHelper::getCoordinateSystemOfAxis( xAxis, ChartModelHelper::findDiagram( xChartModel ) ) );
379             rtl::OUString aCooSysParticle( createParticleForCoordinateSystem( xCooSys, xChartModel ) );
380             sal_Int32 nDimensionIndex=-1;
381             sal_Int32 nAxisIndex=-1;
382             AxisHelper::getIndicesForAxis( xAxis, xCooSys, nDimensionIndex, nAxisIndex );
383             rtl::OUString aAxisParticle( createParticleForAxis( nDimensionIndex, nAxisIndex ) );
384             return createClassifiedIdentifierForParticles( aCooSysParticle, aAxisParticle );
385         }
386 
387         //legend
388         Reference< XLegend > xLegend( xObject, uno::UNO_QUERY );
389         if( xLegend.is() )
390         {
391             return createClassifiedIdentifierForParticle( createParticleForLegend( xLegend, xChartModel ) );
392         }
393 
394         //diagram
395         Reference< XDiagram > xDiagram( xObject, uno::UNO_QUERY );
396         if( xDiagram.is() )
397         {
398             return createClassifiedIdentifierForParticle( createParticleForDiagram( xDiagram, xChartModel ) );
399         }
400 
401         //todo
402         //XDataSeries
403         //CooSys
404         //charttype
405         //datapoint?
406         //Gridproperties
407     }
408     catch( uno::Exception& ex)
409     {
410         ASSERT_EXCEPTION( ex );
411     }
412 
413     if( eObjectType != OBJECTTYPE_UNKNOWN )
414     {
415         aRet = ObjectIdentifier::createClassifiedIdentifierWithParent(
416             eObjectType, aObjectID, aParentParticle, aDragMethodServiceName, aDragParameterString );
417     }
418     else
419     {
420         DBG_ASSERT(false,"give object could not be identifed in createClassifiedIdentifierForObject");
421     }
422 
423     return aRet;
424 }
425 
426 OUString ObjectIdentifier::createClassifiedIdentifierForParticle(
427         const OUString& rParticle )
428 {
429     return ObjectIdentifier::createClassifiedIdentifierForParticles( rParticle, OUString() );
430 }
431 
432 OUString ObjectIdentifier::createClassifiedIdentifierForParticles(
433             const OUString& rParentParticle
434           , const OUString& rChildParticle
435           , const OUString& rDragMethodServiceName
436           , const OUString& rDragParameterString )
437 {
438     ObjectType eObjectType( ObjectIdentifier::getObjectType( rChildParticle ) );
439     if( eObjectType == OBJECTTYPE_UNKNOWN )
440         eObjectType = ObjectIdentifier::getObjectType( rParentParticle );
441 
442     OUStringBuffer aRet( m_aProtocol );
443     aRet.append( lcl_createClassificationStringForType( eObjectType, rDragMethodServiceName, rDragParameterString ));
444     if(aRet.getLength()>m_aProtocol.getLength())
445         aRet.appendAscii("/");
446 
447     if(rParentParticle.getLength())
448     {
449         aRet.append(rParentParticle);
450         if( rChildParticle.getLength() )
451             aRet.appendAscii(":");
452     }
453     aRet.append(rChildParticle);
454 
455     return aRet.makeStringAndClear();
456 }
457 
458 OUString ObjectIdentifier::createParticleForDiagram(
459           const Reference< XDiagram >& /*xDiagram*/
460         , const Reference< frame::XModel >& /*xChartModel*/ )
461 {
462     static OUString aRet(C2U("D=0"));
463     //todo: if more than one diagram is implemeted, add the correct diagram index here
464     return aRet;
465 }
466 
467 OUString ObjectIdentifier::createParticleForCoordinateSystem(
468           const Reference< XCoordinateSystem >& xCooSys
469         , const Reference< frame::XModel >& xChartModel )
470 {
471     OUStringBuffer aRet;
472 
473     Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) );
474     Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
475     if( xCooSysContainer.is() )
476     {
477         sal_Int32 nCooSysIndex = 0;
478         uno::Sequence< Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
479         for( ; nCooSysIndex < aCooSysList.getLength(); ++nCooSysIndex )
480         {
481             Reference< XCoordinateSystem > xCurrentCooSys( aCooSysList[nCooSysIndex] );
482             if( xCooSys == xCurrentCooSys )
483             {
484                 aRet = ObjectIdentifier::createParticleForDiagram( xDiagram, xChartModel );
485                 aRet.appendAscii(":CS=");
486                 aRet.append( OUString::valueOf( nCooSysIndex ) );
487                 break;
488             }
489         }
490     }
491 
492     return aRet.makeStringAndClear();
493 }
494 
495 OUString ObjectIdentifier::createParticleForAxis(
496             sal_Int32 nDimensionIndex
497           , sal_Int32 nAxisIndex )
498 {
499     OUStringBuffer aRet(C2U("Axis="));
500 
501     aRet.append( OUString::valueOf( nDimensionIndex ) );
502     aRet.appendAscii(",");
503     aRet.append( OUString::valueOf( nAxisIndex ) );
504 
505     return aRet.makeStringAndClear();
506 }
507 
508 OUString ObjectIdentifier::createParticleForGrid(
509             sal_Int32 nDimensionIndex
510           , sal_Int32 nAxisIndex )
511 {
512     OUStringBuffer aRet(C2U("Axis="));
513     aRet.append( OUString::valueOf( nDimensionIndex ) );
514     aRet.appendAscii(",");
515     aRet.append( OUString::valueOf( nAxisIndex ) );
516     aRet.append( C2U(":Grid=0") );
517 
518     return aRet.makeStringAndClear();
519 }
520 
521 OUString ObjectIdentifier::createClassifiedIdentifierForGrid(
522           const Reference< XAxis >& xAxis
523         , const Reference< frame::XModel >& xChartModel
524         , sal_Int32 nSubGridIndex )
525 {
526     //-1: main grid, 0: first subgrid etc
527 
528     rtl::OUString aAxisCID( createClassifiedIdentifierForObject( xAxis, xChartModel ) );
529     rtl::OUString aGridCID( addChildParticle( aAxisCID
530         , createChildParticleWithIndex( OBJECTTYPE_GRID, 0 ) ) );
531     if( nSubGridIndex >= 0 )
532     {
533         aGridCID = addChildParticle( aGridCID
534             , createChildParticleWithIndex( OBJECTTYPE_SUBGRID, 0 ) );
535     }
536     return aGridCID;
537 }
538 
539 OUString ObjectIdentifier::createParticleForSeries(
540               sal_Int32 nDiagramIndex, sal_Int32 nCooSysIndex
541             , sal_Int32 nChartTypeIndex, sal_Int32 nSeriesIndex )
542 {
543     OUStringBuffer aRet;
544 
545     aRet.appendAscii("D=");
546     aRet.append( OUString::valueOf( nDiagramIndex ) );
547     aRet.appendAscii(":CS=");
548     aRet.append( OUString::valueOf( nCooSysIndex ) );
549     aRet.appendAscii(":CT=");
550     aRet.append( OUString::valueOf( nChartTypeIndex ) );
551     aRet.appendAscii(":");
552     aRet.append(getStringForType( OBJECTTYPE_DATA_SERIES ));
553     aRet.appendAscii("=");
554     aRet.append( OUString::valueOf( nSeriesIndex ) );
555 
556     return aRet.makeStringAndClear();
557 }
558 
559 OUString ObjectIdentifier::createParticleForLegend(
560           const Reference< XLegend >& /*xLegend*/
561         , const Reference< frame::XModel >& xChartModel )
562 {
563     OUStringBuffer aRet;
564 
565     Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) );
566     //todo: if more than one diagram is implemeted, find the correct diagram wich is owner of the given legend
567 
568     aRet.append( ObjectIdentifier::createParticleForDiagram( xDiagram, xChartModel ) );
569     aRet.appendAscii(":");
570     aRet.append(getStringForType( OBJECTTYPE_LEGEND ));
571     aRet.appendAscii("=");
572 
573     return aRet.makeStringAndClear();
574 }
575 
576 OUString ObjectIdentifier::createClassifiedIdentifier(
577         enum ObjectType eObjectType //e.g. OBJECTTYPE_DATA_SERIES
578         , const OUString& rParticleID )//e.g. SeriesID
579 {
580     return createClassifiedIdentifierWithParent(
581         eObjectType, rParticleID, m_aEmptyString );
582 }
583 
584 OUString ObjectIdentifier::createClassifiedIdentifierWithParent(
585         enum ObjectType eObjectType //e.g. OBJECTTYPE_DATA_POINT or OBJECTTYPE_GRID
586         , const OUString& rParticleID //e.g. Point Index or SubGrid Index
587         , const OUString& rParentPartical //e.g. "Series=SeriesID" or "Grid=GridId"
588         , const OUString& rDragMethodServiceName
589         , const OUString& rDragParameterString
590         )
591         //, bool bIsMultiClickObject ) //e.g. true
592 {
593     //e.g. "MultiClick/Series=2:Point=34"
594 
595     OUStringBuffer aRet( m_aProtocol );
596     aRet.append( lcl_createClassificationStringForType( eObjectType, rDragMethodServiceName, rDragParameterString ));
597     if(aRet.getLength()>m_aProtocol.getLength())
598         aRet.appendAscii("/");
599     aRet.append(rParentPartical);
600     if(rParentPartical.getLength())
601         aRet.appendAscii(":");
602 
603     aRet.append(getStringForType( eObjectType ));
604     aRet.appendAscii("=");
605     aRet.append(rParticleID);
606 
607     return aRet.makeStringAndClear();
608 }
609 
610 const OUString& ObjectIdentifier::getPieSegmentDragMethodServiceName()
611 {
612     return m_aPieSegmentDragMethodServiceName;
613 }
614 
615 OUString ObjectIdentifier::createPieSegmentDragParameterString(
616           sal_Int32 nOffsetPercent
617         , const awt::Point& rMinimumPosition
618         , const awt::Point& rMaximumPosition )
619 {
620     OUStringBuffer aRet( OUString::valueOf( nOffsetPercent ) );
621     aRet.append( sal_Unicode( ',' ));
622     aRet.append( OUString::valueOf( rMinimumPosition.X ) );
623     aRet.append( sal_Unicode( ',' ));
624     aRet.append( OUString::valueOf( rMinimumPosition.Y ) );
625     aRet.append( sal_Unicode( ',' ));
626     aRet.append( OUString::valueOf( rMaximumPosition.X ) );
627     aRet.append( sal_Unicode( ',' ));
628     aRet.append( OUString::valueOf( rMaximumPosition.Y ) );
629     return aRet.makeStringAndClear();
630 }
631 
632 bool ObjectIdentifier::parsePieSegmentDragParameterString(
633           const OUString& rDragParameterString
634         , sal_Int32& rOffsetPercent
635         , awt::Point& rMinimumPosition
636         , awt::Point& rMaximumPosition )
637 {
638     OUString aValue;
639     sal_Int32 nCharacterIndex = 0;
640 
641     OUString aValueString( rDragParameterString.getToken( 0, ',', nCharacterIndex ) );
642     rOffsetPercent = aValueString.toInt32();
643     if( nCharacterIndex < 0 )
644         return false;
645 
646     aValueString = rDragParameterString.getToken( 0, ',', nCharacterIndex );
647     rMinimumPosition.X = aValueString.toInt32();
648     if( nCharacterIndex < 0 )
649         return false;
650 
651     aValueString = rDragParameterString.getToken( 0, ',', nCharacterIndex );
652     rMinimumPosition.Y = aValueString.toInt32();
653     if( nCharacterIndex < 0 )
654         return false;
655 
656     aValueString = rDragParameterString.getToken( 0, ',', nCharacterIndex );
657     rMaximumPosition.X = aValueString.toInt32();
658     if( nCharacterIndex < 0 )
659         return false;
660 
661     aValueString = rDragParameterString.getToken( 0, ',', nCharacterIndex );
662     rMaximumPosition.Y = aValueString.toInt32();
663     if( nCharacterIndex < 0 )
664         return false;
665 
666     return true;
667 }
668 
669 OUString ObjectIdentifier::getDragMethodServiceName( const OUString& rCID )
670 {
671     OUString aRet;
672 
673     sal_Int32 nIndexStart = rCID.indexOf( m_aDragMethodEquals );
674     if( nIndexStart != -1 )
675     {
676         nIndexStart = rCID.indexOf( '=', nIndexStart );
677         if( nIndexStart != -1 )
678         {
679             nIndexStart++;
680             sal_Int32 nNextSlash = rCID.indexOf( '/', nIndexStart );
681             if( nNextSlash != -1 )
682             {
683                 sal_Int32 nIndexEnd = nNextSlash;
684                 sal_Int32 nNextColon = rCID.indexOf( ':', nIndexStart );
685                 if( nNextColon < nNextSlash )
686                     nIndexEnd = nNextColon;
687                 aRet = rCID.copy(nIndexStart,nIndexEnd-nIndexStart);
688             }
689         }
690     }
691     return aRet;
692 }
693 
694 OUString ObjectIdentifier::getDragParameterString( const OUString& rCID )
695 {
696     OUString aRet;
697 
698     sal_Int32 nIndexStart = rCID.indexOf( m_aDragParameterEquals );
699     if( nIndexStart != -1 )
700     {
701         nIndexStart = rCID.indexOf( '=', nIndexStart );
702         if( nIndexStart != -1 )
703         {
704             nIndexStart++;
705             sal_Int32 nNextSlash = rCID.indexOf( '/', nIndexStart );
706             if( nNextSlash != -1 )
707             {
708                 sal_Int32 nIndexEnd = nNextSlash;
709                 sal_Int32 nNextColon = rCID.indexOf( ':', nIndexStart );
710                 if( nNextColon < nNextSlash )
711                     nIndexEnd = nNextColon;
712                 aRet = rCID.copy(nIndexStart,nIndexEnd-nIndexStart);
713             }
714         }
715     }
716     return aRet;
717 }
718 
719 bool ObjectIdentifier::isDragableObject( const OUString& rClassifiedIdentifier )
720 {
721     ObjectType eObjectType = ObjectIdentifier::getObjectType( rClassifiedIdentifier );
722     switch( eObjectType )
723     {
724         case OBJECTTYPE_TITLE:
725         case OBJECTTYPE_LEGEND:
726         case OBJECTTYPE_DIAGRAM:
727         case OBJECTTYPE_DATA_CURVE_EQUATION:
728         //case OBJECTTYPE_DIAGRAM_WALL:
729             return true;
730         default:
731             OUString aDragMethodServiceName( ObjectIdentifier::getDragMethodServiceName( rClassifiedIdentifier ) );
732             if( aDragMethodServiceName.getLength() )
733                 return true;
734             return false;
735     }
736     return false;
737 }
738 
739 bool ObjectIdentifier::isDragableObject()
740 {
741     bool bReturn = false;
742     if ( isAutoGeneratedObject() )
743     {
744         bReturn = isDragableObject( m_aObjectCID );
745     }
746     else if ( isAdditionalShape() )
747     {
748         bReturn = true;
749     }
750     return bReturn;
751 }
752 
753 bool ObjectIdentifier::isRotateableObject( const OUString& rClassifiedIdentifier )
754 {
755     ObjectType eObjectType = ObjectIdentifier::getObjectType( rClassifiedIdentifier );
756     switch( eObjectType )
757     {
758         case OBJECTTYPE_DIAGRAM:
759         //case OBJECTTYPE_DIAGRAM_WALL:
760             return true;
761         default:
762             return false;
763     }
764     return false;
765 }
766 
767 bool ObjectIdentifier::isMultiClickObject( const OUString& rClassifiedIdentifier )
768 {
769     //the name of a shape is it's ClassifiedIdentifier
770 
771     //a MultiClickObject is an object that is selectable by more than one click only ;
772     //before a MultiClickObject can be selected it is necessary that a named parent group object
773     //was selected before;
774 
775     //!!!!! by definition the name of a MultiClickObject starts with "CID/MultiClick:"
776     bool bRet = false;
777     bRet = rClassifiedIdentifier.match( m_aMultiClick, m_aProtocol.getLength() );
778     return bRet;
779 }
780 
781 bool ObjectIdentifier::areSiblings( const OUString& rCID1, const OUString& rCID2 )
782 {
783     bool bRet=false;
784     sal_Int32 nLastSign1 = rCID1.lastIndexOf( '=' );
785     sal_Int32 nLastSign2 = rCID2.lastIndexOf( '=' );
786     if( nLastSign1 == rCID1.indexOf( '=' ) )//CID cannot be sibling if only one "=" occurs
787         bRet=false;
788     else if( nLastSign2 == rCID2.indexOf( '=' ) )//CID cannot be sibling if only one "=" occurs
789         bRet=false;
790     else if( ObjectIdentifier::areIdenticalObjects( rCID1, rCID2 ) )
791         bRet=false;
792     else
793     {
794         OUString aParent1( ObjectIdentifier::getFullParentParticle( rCID1 ) );
795         if( aParent1.getLength() )
796         {
797             OUString aParent2( ObjectIdentifier::getFullParentParticle( rCID2 ) );
798             bRet=aParent1.equals(aParent2);
799         }
800         //legend entries are special:
801         if(!bRet)
802         {
803             if( OBJECTTYPE_LEGEND_ENTRY == getObjectType(rCID1)
804                 && OBJECTTYPE_LEGEND_ENTRY == getObjectType(rCID2) )
805                 bRet = true;
806         }
807     }
808     return bRet;
809 }
810 
811 bool ObjectIdentifier::areIdenticalObjects( const OUString& rCID1, const OUString& rCID2 )
812 {
813     if( rCID1.equals( rCID2 ) )
814         return true;
815     //draggable pie or donut segments need special treatment, as their CIDs do change with offset
816     {
817         if( rCID1.indexOf( m_aPieSegmentDragMethodServiceName ) < 0
818             || rCID2.indexOf( m_aPieSegmentDragMethodServiceName ) < 0 )
819             return false;
820 
821         OUString aID1( ObjectIdentifier::getObjectID( rCID1 ) );
822         OUString aID2( ObjectIdentifier::getObjectID( rCID2 ) );
823         if( aID1.getLength() &&  aID1.equals( aID2 ) )
824             return true;
825         }
826     return false;
827 }
828 
829 OUString ObjectIdentifier::getStringForType( ObjectType eObjectType )
830 {
831     OUString aRet;
832     switch( eObjectType )
833     {
834         case OBJECTTYPE_PAGE:
835                 aRet=C2U("Page");
836                 break;
837         case OBJECTTYPE_TITLE:
838                 aRet=C2U("Title");
839                 break;
840         case OBJECTTYPE_LEGEND:
841                 aRet=C2U("Legend");
842                 break;
843         case OBJECTTYPE_LEGEND_ENTRY:
844                 aRet=C2U("LegendEntry");
845                 break;
846         case OBJECTTYPE_DIAGRAM:
847                 aRet=C2U("D");
848                 break;
849         case OBJECTTYPE_DIAGRAM_WALL:
850                 aRet=C2U("DiagramWall");
851                 break;
852         case OBJECTTYPE_DIAGRAM_FLOOR:
853                 aRet=C2U("DiagramFloor");
854                 break;
855         case OBJECTTYPE_AXIS:
856                 aRet=C2U("Axis");
857                 break;
858         case OBJECTTYPE_AXIS_UNITLABEL:
859                 aRet=C2U("AxisUnitLabel");
860                 break;
861         case OBJECTTYPE_GRID:
862                 aRet=C2U("Grid");
863                 break;
864         case OBJECTTYPE_SUBGRID:
865                 aRet=C2U("SubGrid");
866                 break;
867         case OBJECTTYPE_DATA_SERIES:
868                 aRet=C2U("Series");
869                 break;
870         case OBJECTTYPE_DATA_POINT:
871                 aRet=C2U("Point");
872                 break;
873         case OBJECTTYPE_DATA_LABELS:
874                 aRet=C2U("DataLabels");
875                 break;
876         case OBJECTTYPE_DATA_LABEL:
877                 aRet=C2U("DataLabel");
878                 break;
879         case OBJECTTYPE_DATA_ERRORS:
880                 aRet=C2U("Errors");
881                 break;
882         case OBJECTTYPE_DATA_ERRORS_X:
883                 aRet=C2U("ErrorsX");
884                 break;
885         case OBJECTTYPE_DATA_ERRORS_Y:
886                 aRet=C2U("ErrorsY");
887                 break;
888         case OBJECTTYPE_DATA_ERRORS_Z:
889                 aRet=C2U("ErrorsZ");
890                 break;
891         case OBJECTTYPE_DATA_CURVE:
892                 aRet=C2U("Curve");
893                 break;
894         case OBJECTTYPE_DATA_CURVE_EQUATION:
895                 aRet=C2U("Equation");
896                 break;
897         case OBJECTTYPE_DATA_AVERAGE_LINE:
898                 aRet=C2U("Average");
899                 break;
900         case OBJECTTYPE_DATA_STOCK_RANGE:
901                 aRet=C2U("StockRange");
902                 break;
903         case OBJECTTYPE_DATA_STOCK_LOSS:
904                 aRet=C2U("StockLoss");
905                 break;
906         case OBJECTTYPE_DATA_STOCK_GAIN:
907                 aRet=C2U("StockGain");
908                 break;
909         default: //OBJECTTYPE_UNKNOWN
910             ;
911     }
912     return aRet;
913 }
914 
915 ObjectType ObjectIdentifier::getObjectType( const OUString& rCID )
916 {
917     ObjectType eRet;
918     sal_Int32 nLastSign = rCID.lastIndexOf( ':' );//last sign before the type string
919     if(nLastSign==-1)
920         nLastSign = rCID.lastIndexOf( '/' );
921     if(nLastSign==-1)
922     {
923         sal_Int32 nEndIndex = rCID.lastIndexOf( '=' );
924         if(nEndIndex==-1)
925             return OBJECTTYPE_UNKNOWN;
926         nLastSign = 0;
927     }
928     if( nLastSign>0 )
929         nLastSign++;
930 
931     if( rCID.match(C2U("Page"),nLastSign) )
932         eRet = OBJECTTYPE_PAGE;
933     else if( rCID.match(C2U("Title"),nLastSign) )
934         eRet = OBJECTTYPE_TITLE;
935     else if( rCID.match(C2U("LegendEntry"),nLastSign) )
936         eRet = OBJECTTYPE_LEGEND_ENTRY;
937     else if( rCID.match(C2U("Legend"),nLastSign) )
938         eRet = OBJECTTYPE_LEGEND;
939     else if( rCID.match(C2U("DiagramWall"),nLastSign) )
940         eRet = OBJECTTYPE_DIAGRAM_WALL;
941     else if( rCID.match(C2U("DiagramFloor"),nLastSign) )
942         eRet = OBJECTTYPE_DIAGRAM_FLOOR;
943     else if( rCID.match(C2U("D="),nLastSign) )
944         eRet = OBJECTTYPE_DIAGRAM;
945     else if( rCID.match(C2U("AxisUnitLabel"),nLastSign) )
946         eRet = OBJECTTYPE_AXIS_UNITLABEL;
947     else if( rCID.match(C2U("Axis"),nLastSign) )
948         eRet = OBJECTTYPE_AXIS;
949     else if( rCID.match(C2U("Grid"),nLastSign) )
950         eRet = OBJECTTYPE_GRID;
951     else if( rCID.match(C2U("SubGrid"),nLastSign) )
952         eRet = OBJECTTYPE_SUBGRID;
953     else if( rCID.match(C2U("Series"),nLastSign) )
954         eRet = OBJECTTYPE_DATA_SERIES;
955     else if( rCID.match(C2U("Point"),nLastSign) )
956         eRet = OBJECTTYPE_DATA_POINT;
957     else if( rCID.match(C2U("DataLabels"),nLastSign) )
958         eRet = OBJECTTYPE_DATA_LABELS;
959     else if( rCID.match(C2U("DataLabel"),nLastSign) )
960         eRet = OBJECTTYPE_DATA_LABEL;
961     else if( rCID.match(C2U("ErrorsX"),nLastSign) )
962         eRet = OBJECTTYPE_DATA_ERRORS_X;
963     else if( rCID.match(C2U("ErrorsY"),nLastSign) )
964         eRet = OBJECTTYPE_DATA_ERRORS_Y;
965     else if( rCID.match(C2U("ErrorsZ"),nLastSign) )
966         eRet = OBJECTTYPE_DATA_ERRORS_Z;
967     else if( rCID.match(C2U("Errors"),nLastSign) )
968         eRet = OBJECTTYPE_DATA_ERRORS;
969     else if( rCID.match(C2U("Curve"),nLastSign) )
970         eRet = OBJECTTYPE_DATA_CURVE;
971     else if( rCID.match(C2U("Equation"),nLastSign) )
972         eRet = OBJECTTYPE_DATA_CURVE_EQUATION;
973     else if( rCID.match(C2U("Average"),nLastSign) )
974         eRet = OBJECTTYPE_DATA_AVERAGE_LINE;
975     else if( rCID.match(C2U("StockRange"),nLastSign) )
976         eRet = OBJECTTYPE_DATA_STOCK_RANGE;
977     else if( rCID.match(C2U("StockLoss"),nLastSign) )
978         eRet = OBJECTTYPE_DATA_STOCK_LOSS;
979     else if( rCID.match(C2U("StockGain"),nLastSign) )
980         eRet = OBJECTTYPE_DATA_STOCK_GAIN;
981     else
982         eRet = OBJECTTYPE_UNKNOWN;
983 
984     return eRet;
985 }
986 
987 ObjectType ObjectIdentifier::getObjectType()
988 {
989     ObjectType eObjectType( OBJECTTYPE_UNKNOWN );
990     if ( isAutoGeneratedObject() )
991     {
992         eObjectType = getObjectType( m_aObjectCID );
993     }
994     else if ( isAdditionalShape() )
995     {
996         eObjectType = OBJECTTYPE_SHAPE;
997     }
998     return eObjectType;
999 }
1000 
1001 OUString ObjectIdentifier::createDataCurveCID(
1002                                 const OUString& rSeriesParticle
1003                                 , sal_Int32 nCurveIndex
1004                                 , bool bAverageLine )
1005 {
1006     OUString aParticleID( OUString::valueOf( nCurveIndex ) );
1007     ObjectType eType = bAverageLine ? OBJECTTYPE_DATA_AVERAGE_LINE : OBJECTTYPE_DATA_CURVE;
1008     return createClassifiedIdentifierWithParent( eType, aParticleID, rSeriesParticle );
1009 }
1010 
1011 OUString ObjectIdentifier::createDataCurveEquationCID(
1012                                 const OUString& rSeriesParticle
1013                                 , sal_Int32 nCurveIndex )
1014 {
1015     OUString aParticleID( OUString::valueOf( nCurveIndex ) );
1016     return createClassifiedIdentifierWithParent( OBJECTTYPE_DATA_CURVE_EQUATION, aParticleID, rSeriesParticle );
1017 }
1018 
1019 OUString ObjectIdentifier::addChildParticle( const rtl::OUString& rParticle, const rtl::OUString& rChildParticle )
1020 {
1021     OUStringBuffer aRet(rParticle);
1022 
1023     if( aRet.getLength() && rChildParticle.getLength() )
1024         aRet.appendAscii(":");
1025     if( rChildParticle.getLength() )
1026         aRet.append(rChildParticle);
1027 
1028     return aRet.makeStringAndClear();
1029 }
1030 
1031 rtl::OUString ObjectIdentifier::createChildParticleWithIndex( ObjectType eObjectType, sal_Int32 nIndex )
1032 {
1033     OUStringBuffer aRet( getStringForType( eObjectType ) );
1034     if( aRet.getLength() )
1035     {
1036         aRet.appendAscii("=");
1037         aRet.append(OUString::valueOf(nIndex));
1038     }
1039     return aRet.makeStringAndClear();
1040 }
1041 
1042 sal_Int32 ObjectIdentifier::getIndexFromParticleOrCID( const rtl::OUString& rParticleOrCID )
1043 {
1044     sal_Int32 nRet = -1;
1045 
1046     OUString aIndexString = lcl_getIndexStringAfterString( rParticleOrCID, C2U("=") );
1047     sal_Int32 nCharacterIndex=0;
1048     nRet = lcl_StringToIndex( aIndexString.getToken( 0, ',', nCharacterIndex ) );
1049 
1050     return nRet;
1051 }
1052 
1053 OUString ObjectIdentifier::createSeriesSubObjectStub( ObjectType eSubObjectType
1054                     , const rtl::OUString& rSeriesParticle
1055                     , const rtl::OUString& rDragMethodServiceName
1056                     , const rtl::OUString& rDragParameterString )
1057 {
1058     OUString aChildParticle( getStringForType( eSubObjectType ) );
1059     aChildParticle+=(C2U("="));
1060 
1061     return createClassifiedIdentifierForParticles(
1062             rSeriesParticle, aChildParticle
1063           , rDragMethodServiceName, rDragParameterString );
1064 }
1065 
1066 OUString ObjectIdentifier::createPointCID( const OUString& rPointCID_Stub, sal_Int32 nIndex  )
1067 {
1068     OUString aRet(rPointCID_Stub);
1069     return aRet+=OUString::valueOf( nIndex );
1070 }
1071 
1072 OUString ObjectIdentifier::getParticleID( const OUString& rCID )
1073 {
1074     OUString aRet;
1075     sal_Int32 nLast = rCID.lastIndexOf('=');
1076     if(nLast>=0)
1077         aRet = rCID.copy(++nLast);
1078     return aRet;
1079 }
1080 
1081 OUString ObjectIdentifier::getFullParentParticle( const OUString& rCID )
1082 {
1083     OUString aRet;
1084 
1085     sal_Int32 nStartPos = rCID.lastIndexOf('/');
1086     if( nStartPos>=0 )
1087     {
1088         nStartPos++;
1089         sal_Int32 nEndPos = rCID.lastIndexOf(':');
1090         if( nEndPos>=0 && nStartPos < nEndPos )
1091         {
1092             aRet = rCID.copy(nStartPos,nEndPos-nStartPos);
1093         }
1094     }
1095 
1096     return aRet;
1097 }
1098 
1099 OUString ObjectIdentifier::getObjectID( const rtl::OUString& rCID )
1100 {
1101     OUString aRet;
1102 
1103     sal_Int32 nStartPos = rCID.lastIndexOf('/');
1104     if( nStartPos>=0 )
1105     {
1106         nStartPos++;
1107         sal_Int32 nEndPos = rCID.getLength();
1108         aRet = rCID.copy(nStartPos,nEndPos-nStartPos);
1109     }
1110 
1111     return aRet;
1112 }
1113 
1114 bool ObjectIdentifier::isCID( const OUString& rName )
1115 {
1116     return rName.getLength() && rName.match( m_aProtocol );
1117 }
1118 
1119 Reference< beans::XPropertySet > ObjectIdentifier::getObjectPropertySet(
1120     const OUString& rObjectCID,
1121     const Reference< chart2::XChartDocument >& xChartDocument )
1122 {
1123     return ObjectIdentifier::getObjectPropertySet(
1124         rObjectCID, Reference< frame::XModel >( xChartDocument, uno::UNO_QUERY ));
1125 }
1126 
1127 Reference< beans::XPropertySet > ObjectIdentifier::getObjectPropertySet(
1128                 const OUString& rObjectCID
1129                 , const Reference< frame::XModel >& xChartModel )
1130 {
1131     //return the model object that is indicated by rObjectCID
1132     if(!rObjectCID.getLength())
1133         return NULL;
1134     if(!xChartModel.is())
1135         return NULL;
1136 
1137     Reference< beans::XPropertySet > xObjectProperties = NULL;
1138     try
1139     {
1140         ObjectType eObjectType = ObjectIdentifier::getObjectType( rObjectCID );
1141         OUString aParticleID = ObjectIdentifier::getParticleID( rObjectCID );
1142 
1143         Reference< XDiagram > xDiagram;
1144         Reference< XCoordinateSystem > xCooSys;
1145         lcl_getDiagramAndCooSys( rObjectCID, xChartModel, xDiagram, xCooSys );
1146 
1147         switch(eObjectType)
1148         {
1149             case OBJECTTYPE_PAGE:
1150                 {
1151                     Reference< XChartDocument > xChartDocument( xChartModel, uno::UNO_QUERY );
1152                     if( xChartDocument.is())
1153                         xObjectProperties.set( xChartDocument->getPageBackground() );
1154                 }
1155                 break;
1156             case OBJECTTYPE_TITLE:
1157                 {
1158                     TitleHelper::eTitleType aTitleType = getTitleTypeForCID( rObjectCID );
1159                     Reference< XTitle > xTitle( TitleHelper::getTitle( aTitleType, xChartModel ) );
1160                     xObjectProperties.set( xTitle, uno::UNO_QUERY );
1161                 }
1162                 break;
1163             case OBJECTTYPE_LEGEND:
1164                 {
1165                     if( xDiagram.is() )
1166                         xObjectProperties.set( xDiagram->getLegend(), uno::UNO_QUERY );
1167                 }
1168                 break;
1169             case OBJECTTYPE_LEGEND_ENTRY:
1170                     break;
1171             case OBJECTTYPE_DIAGRAM:
1172                 {
1173                     xObjectProperties.set( xDiagram, uno::UNO_QUERY );
1174                 }
1175                 break;
1176             case OBJECTTYPE_DIAGRAM_WALL:
1177                 {
1178                     if( xDiagram.is() )
1179                         xObjectProperties.set( xDiagram->getWall() );
1180                 }
1181                 break;
1182             case OBJECTTYPE_DIAGRAM_FLOOR:
1183                 {
1184                     if( xDiagram.is() )
1185                         xObjectProperties.set( xDiagram->getFloor() );
1186                 }
1187                 break;
1188             case OBJECTTYPE_AXIS:
1189                 {
1190                     sal_Int32 nDimensionIndex = -1;
1191                     sal_Int32 nAxisIndex = -1;
1192                     lcl_parseAxisIndices( nDimensionIndex, nAxisIndex, rObjectCID );
1193 
1194                     Reference< chart2::XAxis > xAxis(
1195                         AxisHelper::getAxis( nDimensionIndex, nAxisIndex, xCooSys ) );
1196                     if( xAxis.is() )
1197                         xObjectProperties.set( xAxis, uno::UNO_QUERY );
1198                 }
1199                 break;
1200             case OBJECTTYPE_AXIS_UNITLABEL:
1201                     break;
1202             case OBJECTTYPE_GRID:
1203             case OBJECTTYPE_SUBGRID:
1204                 {
1205                     sal_Int32 nDimensionIndex = -1;
1206                     sal_Int32 nAxisIndex = -1;
1207                     lcl_parseAxisIndices( nDimensionIndex, nAxisIndex, rObjectCID );
1208 
1209                     sal_Int32 nSubGridIndex = -1;
1210                     lcl_parseGridIndices( nSubGridIndex, rObjectCID );
1211 
1212                     xObjectProperties.set( AxisHelper::getGridProperties( xCooSys , nDimensionIndex, nAxisIndex, nSubGridIndex ) );
1213                 }
1214                 break;
1215             case OBJECTTYPE_DATA_LABELS:
1216             case OBJECTTYPE_DATA_SERIES:
1217                 {
1218                     Reference< XDataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID(
1219                         rObjectCID, xChartModel ) );
1220                     if( xSeries.is() )
1221                         xObjectProperties = Reference< beans::XPropertySet >( xSeries, uno::UNO_QUERY );
1222 
1223                     break;
1224                 }
1225             case OBJECTTYPE_DATA_LABEL:
1226             case OBJECTTYPE_DATA_POINT:
1227                 {
1228                     Reference< XDataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID(
1229                         rObjectCID, xChartModel ) );
1230                     if(xSeries.is())
1231                     {
1232                         sal_Int32 nIndex = aParticleID.toInt32();
1233                         xObjectProperties = xSeries->getDataPointByIndex( nIndex );
1234                     }
1235                     break;
1236                 }
1237             case OBJECTTYPE_DATA_ERRORS:
1238                 {
1239                     Reference< XDataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID(
1240                         rObjectCID, xChartModel ) );
1241                     if(xSeries.is())
1242                     {
1243                         Reference< beans::XPropertySet > xSeriesProp( xSeries, uno::UNO_QUERY );
1244                         Reference< beans::XPropertySet > xErrorBarProp;
1245                         if( xSeriesProp.is() )
1246                         {
1247                             xSeriesProp->getPropertyValue( C2U( "ErrorBarY" )) >>= xErrorBarProp;
1248                             xObjectProperties = Reference< beans::XPropertySet >( xErrorBarProp, uno::UNO_QUERY );
1249                         }
1250                     }
1251                     break;
1252                 }
1253             case OBJECTTYPE_DATA_ERRORS_X:
1254                     break;
1255             case OBJECTTYPE_DATA_ERRORS_Y:
1256                     break;
1257             case OBJECTTYPE_DATA_ERRORS_Z:
1258                     break;
1259             case OBJECTTYPE_DATA_AVERAGE_LINE:
1260             case OBJECTTYPE_DATA_CURVE:
1261             case OBJECTTYPE_DATA_CURVE_EQUATION:
1262                 {
1263                     Reference< XRegressionCurveContainer > xRegressionContainer( ObjectIdentifier::getDataSeriesForCID(
1264                         rObjectCID, xChartModel ), uno::UNO_QUERY );
1265                     if(xRegressionContainer.is())
1266                     {
1267                         sal_Int32 nIndex = aParticleID.toInt32();
1268                         uno::Sequence< Reference< XRegressionCurve > > aCurveList =
1269                             xRegressionContainer->getRegressionCurves();
1270                         if( nIndex >= 0 && nIndex <aCurveList.getLength() )
1271                         {
1272                             if( eObjectType == OBJECTTYPE_DATA_CURVE_EQUATION )
1273                                 xObjectProperties.set( aCurveList[nIndex]->getEquationProperties());
1274                             else
1275                                 xObjectProperties.set( aCurveList[nIndex], uno::UNO_QUERY );
1276                         }
1277                     }
1278                     break;
1279                 }
1280             case OBJECTTYPE_DATA_STOCK_RANGE:
1281                     break;
1282             case OBJECTTYPE_DATA_STOCK_LOSS:
1283                     {
1284                         Reference<XChartType> xChartType( lcl_getFirstStockChartType( xChartModel ) );
1285                         Reference< beans::XPropertySet > xChartTypeProps( xChartType, uno::UNO_QUERY );
1286                         if(xChartTypeProps.is())
1287                             xChartTypeProps->getPropertyValue( C2U( "BlackDay" ) ) >>= xObjectProperties;
1288                     }
1289                     break;
1290             case OBJECTTYPE_DATA_STOCK_GAIN:
1291                     {
1292                         Reference<XChartType> xChartType( lcl_getFirstStockChartType( xChartModel ) );
1293                         Reference< beans::XPropertySet > xChartTypeProps( xChartType, uno::UNO_QUERY );
1294                         if(xChartTypeProps.is())
1295                             xChartTypeProps->getPropertyValue( C2U( "WhiteDay" ) ) >>= xObjectProperties;
1296                     }
1297                     break;
1298             default: //OBJECTTYPE_UNKNOWN
1299                     break;
1300         }
1301     }
1302     catch( uno::Exception& ex)
1303     {
1304         ASSERT_EXCEPTION( ex );
1305     }
1306     return xObjectProperties;
1307 }
1308 
1309 Reference< XAxis > ObjectIdentifier::getAxisForCID(
1310                 const OUString& rObjectCID
1311                 , const Reference< frame::XModel >& xChartModel )
1312 {
1313     Reference< XDiagram > xDiagram;
1314     Reference< XCoordinateSystem > xCooSys;
1315     lcl_getDiagramAndCooSys( rObjectCID, xChartModel, xDiagram, xCooSys );
1316 
1317     sal_Int32 nDimensionIndex = -1;
1318     sal_Int32 nAxisIndex = -1;
1319     lcl_parseAxisIndices( nDimensionIndex, nAxisIndex, rObjectCID );
1320 
1321     return AxisHelper::getAxis( nDimensionIndex, nAxisIndex, xCooSys );
1322 }
1323 
1324 Reference< XDataSeries > ObjectIdentifier::getDataSeriesForCID(
1325                 const OUString& rObjectCID
1326                 , const Reference< frame::XModel >& xChartModel )
1327 {
1328     Reference< XDataSeries > xSeries(NULL);
1329 
1330     Reference< XDiagram > xDiagram;
1331     Reference< XCoordinateSystem > xCooSys;
1332     lcl_getDiagramAndCooSys( rObjectCID, xChartModel, xDiagram, xCooSys );
1333 
1334     sal_Int32 nChartTypeIndex = -1;
1335     sal_Int32 nSeriesIndex = -1;
1336     sal_Int32 nPointIndex = -1;
1337     lcl_parseSeriesIndices( nChartTypeIndex, nSeriesIndex, nPointIndex, rObjectCID );
1338 
1339     Reference< XDataSeriesContainer > xDataSeriesContainer( DiagramHelper::getChartTypeByIndex( xDiagram, nChartTypeIndex ), uno::UNO_QUERY );
1340     if( xDataSeriesContainer.is() )
1341     {
1342         uno::Sequence< uno::Reference< XDataSeries > > aDataSeriesSeq( xDataSeriesContainer->getDataSeries() );
1343         if( nSeriesIndex >= 0 && nSeriesIndex < aDataSeriesSeq.getLength() )
1344             xSeries.set( aDataSeriesSeq[nSeriesIndex] );
1345     }
1346 
1347     return xSeries;
1348 }
1349 
1350 Reference< XDiagram > ObjectIdentifier::getDiagramForCID(
1351                   const rtl::OUString& rObjectCID
1352                 , const uno::Reference< frame::XModel >& xChartModel )
1353 {
1354     Reference< XDiagram > xDiagram;
1355 
1356     Reference< XCoordinateSystem > xCooSys;
1357     lcl_getDiagramAndCooSys( rObjectCID, xChartModel, xDiagram, xCooSys );
1358 
1359     return xDiagram;
1360 }
1361 
1362 TitleHelper::eTitleType ObjectIdentifier::getTitleTypeForCID( const OUString& rCID )
1363 {
1364     TitleHelper::eTitleType eRet( TitleHelper::MAIN_TITLE );
1365 
1366     OUString aParentParticle = ObjectIdentifier::getFullParentParticle( rCID );
1367     const tTitleMap& rMap = lcl_getTitleMap();
1368     tTitleMap::const_iterator aIt( rMap.begin() );
1369     for( ;aIt != rMap.end(); ++aIt )
1370     {
1371         if( aParentParticle.equals( (*aIt).second ) )
1372         {
1373             eRet = (*aIt).first;
1374             break;
1375         }
1376     }
1377 
1378     return eRet;
1379 }
1380 
1381 OUString ObjectIdentifier::getSeriesParticleFromCID( const OUString& rCID )
1382 {
1383     sal_Int32 nDiagramIndex = -1;
1384     sal_Int32 nCooSysIndex = -1;
1385     lcl_parseCooSysIndices( nDiagramIndex, nCooSysIndex, rCID );
1386 
1387     sal_Int32 nChartTypeIndex = -1;
1388     sal_Int32 nSeriesIndex = -1;
1389     sal_Int32 nPointIndex = -1;
1390     lcl_parseSeriesIndices( nChartTypeIndex, nSeriesIndex, nPointIndex, rCID );
1391 
1392     return ObjectIdentifier::createParticleForSeries( nDiagramIndex, nCooSysIndex, nChartTypeIndex, nSeriesIndex );
1393 }
1394 
1395 OUString ObjectIdentifier::getMovedSeriesCID( const ::rtl::OUString& rObjectCID, sal_Bool bForward )
1396 {
1397     sal_Int32 nDiagramIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rObjectCID, C2U("CID/D=") ) );
1398     sal_Int32 nCooSysIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rObjectCID, C2U("CS=") ) );
1399     sal_Int32 nChartTypeIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rObjectCID, C2U("CT=") ) );
1400     sal_Int32 nSeriesIndex = lcl_StringToIndex( lcl_getIndexStringAfterString( rObjectCID, C2U("Series=") ) );
1401 
1402     if( bForward )
1403         nSeriesIndex--;
1404     else
1405         nSeriesIndex++;
1406 
1407     OUString aRet = ObjectIdentifier::createParticleForSeries( nDiagramIndex, nCooSysIndex, nChartTypeIndex, nSeriesIndex );
1408     return ObjectIdentifier::createClassifiedIdentifierForParticle( aRet );
1409 }
1410 
1411 bool ObjectIdentifier::isValid() const
1412 {
1413     return ( isAutoGeneratedObject() || isAdditionalShape() );
1414 }
1415 
1416 bool ObjectIdentifier::isAutoGeneratedObject() const
1417 {
1418     return ( m_aObjectCID.getLength() > 0 );
1419 }
1420 
1421 bool ObjectIdentifier::isAdditionalShape() const
1422 {
1423     return m_xAdditionalShape.is();
1424 }
1425 
1426 OUString ObjectIdentifier::getObjectCID() const
1427 {
1428     return m_aObjectCID;
1429 }
1430 
1431 Reference< drawing::XShape > ObjectIdentifier::getAdditionalShape() const
1432 {
1433     return m_xAdditionalShape;
1434 }
1435 
1436 Any ObjectIdentifier::getAny() const
1437 {
1438     Any aAny;
1439     if ( isAutoGeneratedObject() )
1440     {
1441         aAny = uno::makeAny( getObjectCID() );
1442     }
1443     else if ( isAdditionalShape() )
1444     {
1445         aAny = uno::makeAny( getAdditionalShape() );
1446     }
1447     return aAny;
1448 }
1449 
1450 //.............................................................................
1451 } //namespace chart
1452 //.............................................................................
1453