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