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