Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "ObjectHierarchy.hxx"
21 : #include "ObjectIdentifier.hxx"
22 : #include "ChartModelHelper.hxx"
23 : #include "DiagramHelper.hxx"
24 : #include "RegressionCurveHelper.hxx"
25 : #include "AxisHelper.hxx"
26 : #include "chartview/ExplicitValueProvider.hxx"
27 : #include "macros.hxx"
28 : #include "LineProperties.hxx"
29 : #include "ChartTypeHelper.hxx"
30 : #include "DataSeriesHelper.hxx"
31 : #include "LegendHelper.hxx"
32 : #include "chartview/DrawModelWrapper.hxx"
33 :
34 : #include <map>
35 : #include <algorithm>
36 :
37 : #include <com/sun/star/chart2/XTitled.hpp>
38 : #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
39 : #include <com/sun/star/chart2/XChartTypeContainer.hpp>
40 : #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
41 : #include <com/sun/star/chart/ErrorBarStyle.hpp>
42 :
43 : #include <com/sun/star/container/XIndexAccess.hpp>
44 : #include <com/sun/star/awt/Key.hpp>
45 : #include <com/sun/star/awt/KeyModifier.hpp>
46 :
47 : using namespace ::com::sun::star;
48 : using namespace ::com::sun::star::chart2;
49 :
50 : using ::com::sun::star::uno::Reference;
51 : using ::com::sun::star::uno::Sequence;
52 :
53 : namespace
54 : {
55 :
56 0 : struct lcl_ObjectToOID : public ::std::unary_function< Reference< uno::XInterface >, ::chart::ObjectIdentifier >
57 : {
58 0 : explicit lcl_ObjectToOID( const Reference< chart2::XChartDocument > & xChartDoc ) :
59 0 : m_xModel( xChartDoc, uno::UNO_QUERY )
60 0 : {}
61 :
62 0 : ::chart::ObjectIdentifier operator() ( const Reference< uno::XInterface > & xObj )
63 : {
64 0 : return ::chart::ObjectIdentifier( ::chart::ObjectIdentifier::createClassifiedIdentifierForObject( xObj, m_xModel ) );
65 : }
66 :
67 : private:
68 : Reference< frame::XModel > m_xModel;
69 : };
70 :
71 0 : void lcl_getChildOIDs(
72 : ::chart::ObjectHierarchy::tChildContainer& rOutChildren,
73 : const Reference< container::XIndexAccess >& xShapes )
74 : {
75 0 : if( xShapes.is())
76 : {
77 0 : sal_Int32 nCount = xShapes->getCount();
78 0 : for( sal_Int32 i=0; i<nCount; ++i)
79 : {
80 0 : Reference< beans::XPropertySet > xShapeProp( xShapes->getByIndex( i ), uno::UNO_QUERY );
81 0 : if( xShapeProp.is())
82 : {
83 0 : Reference< beans::XPropertySetInfo > xInfo( xShapeProp->getPropertySetInfo());
84 0 : OUString aName;
85 0 : if( xInfo.is() &&
86 0 : xInfo->hasPropertyByName( "Name") &&
87 0 : (xShapeProp->getPropertyValue( "Name") >>= aName ) &&
88 0 : !aName.isEmpty() &&
89 0 : ::chart::ObjectIdentifier::isCID( aName ))
90 : {
91 0 : rOutChildren.push_back( ::chart::ObjectIdentifier( aName ) );
92 : }
93 0 : Reference< container::XIndexAccess > xNewShapes( xShapeProp, uno::UNO_QUERY );
94 0 : if( xNewShapes.is())
95 0 : lcl_getChildOIDs( rOutChildren, xNewShapes );
96 : }
97 0 : }
98 : }
99 0 : }
100 :
101 0 : void lcl_addAxisTitle( const Reference< XAxis >& xAxis, ::chart::ObjectHierarchy::tChildContainer& rContainer, const Reference< frame::XModel >& xChartModel )
102 : {
103 0 : Reference< XTitled > xAxisTitled( xAxis, uno::UNO_QUERY );
104 0 : if( xAxisTitled.is())
105 : {
106 0 : Reference< XTitle > xAxisTitle( xAxisTitled->getTitleObject());
107 0 : if( xAxisTitle.is())
108 : rContainer.push_back(
109 0 : ::chart::ObjectIdentifier( ::chart::ObjectIdentifier::createClassifiedIdentifierForObject( xAxisTitle, xChartModel ) ) );
110 0 : }
111 0 : }
112 :
113 : } // anonymous namespace
114 :
115 : namespace chart
116 : {
117 :
118 : namespace impl
119 : {
120 :
121 0 : class ImplObjectHierarchy
122 : {
123 : public:
124 : explicit ImplObjectHierarchy(
125 : const Reference< XChartDocument >& xChartDocument,
126 : ExplicitValueProvider* pExplicitValueProvider,
127 : bool bFlattenDiagram, bool bOrderingForElementSelector );
128 :
129 : bool hasChildren( const ObjectHierarchy::tOID& rParent );
130 : ObjectHierarchy::tChildContainer getChildren( const ObjectHierarchy::tOID& rParent );
131 : ObjectHierarchy::tChildContainer getSiblings( const ObjectHierarchy::tOID& rNode );
132 :
133 : ObjectHierarchy::tOID getParent( const ObjectHierarchy::tOID& rOID );
134 :
135 : private:
136 : void createTree( const Reference< XChartDocument > & xChartDocument );
137 : void createAxesTree(
138 : ObjectHierarchy::tChildContainer & rContainer,
139 : const Reference< XChartDocument > & xChartDoc,
140 : const Reference< XDiagram > & xDiagram );
141 : void createDiagramTree(
142 : ObjectHierarchy::tChildContainer& rContainer,
143 : const Reference< XChartDocument >& xChartDoc,
144 : const Reference< XDiagram >& xDiagram );
145 : void createDataSeriesTree(
146 : ObjectHierarchy::tChildContainer & rOutDiagramSubContainer,
147 : const Reference< XDiagram > & xDiagram );
148 : void createWallAndFloor(
149 : ObjectHierarchy::tChildContainer & rContainer,
150 : const Reference< XDiagram > & xDiagram );
151 : void createLegendTree(
152 : ObjectHierarchy::tChildContainer & rContainer,
153 : const Reference< XChartDocument > & xChartDoc,
154 : const Reference< XDiagram > & xDiagram );
155 : void createAdditionalShapesTree( ObjectHierarchy::tChildContainer& rContainer );
156 :
157 : ObjectHierarchy::tOID getParentImpl(
158 : const ObjectHierarchy::tOID& rParentOID,
159 : const ObjectHierarchy::tOID& rOID );
160 :
161 : typedef ::std::map< ObjectHierarchy::tOID, ObjectHierarchy::tChildContainer >
162 : tChildMap;
163 : tChildMap m_aChildMap;
164 : ExplicitValueProvider* m_pExplicitValueProvider;
165 : bool m_bFlattenDiagram;
166 : bool m_bOrderingForElementSelector;
167 : };
168 :
169 0 : ImplObjectHierarchy::ImplObjectHierarchy(
170 : const Reference< XChartDocument >& xChartDocument,
171 : ExplicitValueProvider* pExplicitValueProvider,
172 : bool bFlattenDiagram,
173 : bool bOrderingForElementSelector ) :
174 : m_pExplicitValueProvider( pExplicitValueProvider ),
175 : m_bFlattenDiagram( bFlattenDiagram ),
176 0 : m_bOrderingForElementSelector( bOrderingForElementSelector )
177 : {
178 0 : createTree( xChartDocument );
179 : // don't remember this helper to avoid access after lifetime
180 0 : m_pExplicitValueProvider = 0;
181 0 : }
182 :
183 0 : void ImplObjectHierarchy::createTree( const Reference< XChartDocument >& xChartDocument )
184 : {
185 0 : m_aChildMap = tChildMap();//clear tree
186 :
187 0 : if( !xChartDocument.is() )
188 0 : return;
189 :
190 : //@todo: change ObjectIdentifier to take an XChartDocument rather than XModel
191 0 : Reference< frame::XModel > xModel( xChartDocument, uno::UNO_QUERY );
192 0 : Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartDocument ) );
193 0 : ObjectHierarchy::tOID aDiaOID;
194 0 : if( xDiagram.is() )
195 0 : aDiaOID = ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( xDiagram, xModel ) );
196 0 : ObjectHierarchy::tChildContainer aTopLevelContainer;
197 :
198 : // First Level
199 :
200 : // Chart Area
201 0 : if( m_bOrderingForElementSelector )
202 : {
203 0 : aTopLevelContainer.push_back( ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, OUString() ) ) );
204 0 : if( xDiagram.is() )
205 : {
206 0 : aTopLevelContainer.push_back( aDiaOID );
207 0 : createWallAndFloor( aTopLevelContainer, xDiagram );
208 0 : createLegendTree( aTopLevelContainer, xChartDocument, xDiagram );
209 : }
210 : }
211 :
212 : // Main Title
213 0 : Reference< XTitled > xDocTitled( xChartDocument, uno::UNO_QUERY );
214 0 : if( xDocTitled.is())
215 : {
216 0 : Reference< XTitle > xMainTitle( xDocTitled->getTitleObject());
217 0 : if( xMainTitle.is())
218 : aTopLevelContainer.push_back(
219 0 : ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( xMainTitle, xModel ) ) );
220 : }
221 :
222 0 : if( xDiagram.is())
223 : {
224 : // Sub Title. Note: This is interpreted of being top level
225 0 : Reference< XTitled > xDiaTitled( xDiagram, uno::UNO_QUERY );
226 0 : if( xDiaTitled.is())
227 : {
228 0 : Reference< XTitle > xSubTitle( xDiaTitled->getTitleObject());
229 0 : if( xSubTitle.is())
230 : aTopLevelContainer.push_back(
231 0 : ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( xSubTitle, xModel ) ) );
232 : }
233 :
234 0 : if( !m_bOrderingForElementSelector )
235 : {
236 : // Axis Titles. Note: These are interpreted of being top level
237 0 : Sequence< Reference< XAxis > > aAxes( AxisHelper::getAllAxesOfDiagram( xDiagram ) );
238 0 : for( sal_Int32 i=0; i<aAxes.getLength(); ++i )
239 0 : lcl_addAxisTitle( aAxes[i], aTopLevelContainer, xModel );
240 :
241 : // Diagram
242 0 : aTopLevelContainer.push_back( aDiaOID );
243 : }
244 :
245 0 : if( m_bFlattenDiagram )
246 0 : createDiagramTree( aTopLevelContainer, xChartDocument, xDiagram );
247 : else
248 : {
249 0 : ObjectHierarchy::tChildContainer aSubContainer;
250 0 : createDiagramTree( aSubContainer, xChartDocument, xDiagram );
251 0 : if( !aSubContainer.empty() )
252 0 : m_aChildMap[ aDiaOID ] = aSubContainer;
253 : }
254 :
255 0 : if( !m_bOrderingForElementSelector )
256 0 : createLegendTree( aTopLevelContainer, xChartDocument, xDiagram );
257 : }
258 :
259 : // #i12587# support for shapes in chart
260 0 : if ( !m_bOrderingForElementSelector )
261 : {
262 0 : createAdditionalShapesTree( aTopLevelContainer );
263 : }
264 :
265 : // Chart Area
266 0 : if( !m_bOrderingForElementSelector )
267 : aTopLevelContainer.push_back(
268 0 : ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, OUString() ) ) );
269 :
270 0 : if( ! aTopLevelContainer.empty())
271 0 : m_aChildMap[ ObjectHierarchy::getRootNodeOID() ] = aTopLevelContainer;
272 : }
273 :
274 0 : void ImplObjectHierarchy::createLegendTree(
275 : ObjectHierarchy::tChildContainer & rContainer,
276 : const Reference< XChartDocument > & xChartDoc,
277 : const Reference< XDiagram > & xDiagram )
278 : {
279 0 : if( xDiagram.is() && LegendHelper::hasLegend( xDiagram ) )
280 : {
281 0 : ObjectHierarchy::tOID aLegendOID( ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( xDiagram->getLegend(), Reference< frame::XModel >( xChartDoc, uno::UNO_QUERY ) ) ) );
282 0 : rContainer.push_back( aLegendOID );
283 :
284 : // iterate over child shapes of legend and search for matching CIDs
285 0 : if( m_pExplicitValueProvider )
286 : {
287 : Reference< container::XIndexAccess > xLegendShapeContainer(
288 0 : m_pExplicitValueProvider->getShapeForCID( aLegendOID.getObjectCID() ), uno::UNO_QUERY );
289 0 : ObjectHierarchy::tChildContainer aLegendEntryOIDs;
290 0 : lcl_getChildOIDs( aLegendEntryOIDs, xLegendShapeContainer );
291 :
292 0 : m_aChildMap[ aLegendOID ] = aLegendEntryOIDs;
293 0 : }
294 : }
295 0 : }
296 :
297 0 : void ImplObjectHierarchy::createAxesTree(
298 : ObjectHierarchy::tChildContainer & rContainer,
299 : const Reference< XChartDocument > & xChartDoc,
300 : const Reference< XDiagram > & xDiagram )
301 : {
302 0 : Reference< XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW );
303 0 : sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram );
304 0 : uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) );
305 0 : bool bSupportsAxesGrids = ChartTypeHelper::isSupportingMainAxis( xChartType, nDimensionCount, 0 );
306 0 : if( bSupportsAxesGrids )
307 : {
308 0 : Sequence< Reference< XAxis > > aAxes( AxisHelper::getAllAxesOfDiagram( xDiagram, /* bOnlyVisible = */ true ) );
309 0 : if( !m_bOrderingForElementSelector )
310 0 : ::std::transform( aAxes.getConstArray(), aAxes.getConstArray() + aAxes.getLength(),
311 : ::std::back_inserter( rContainer ),
312 0 : lcl_ObjectToOID( xChartDoc ));
313 :
314 : // get all axes, also invisible ones
315 0 : aAxes = AxisHelper::getAllAxesOfDiagram( xDiagram, /* bOnlyVisible = */ false );
316 : // Grids
317 0 : Reference< frame::XModel > xChartModel( xChartDoc, uno::UNO_QUERY );
318 0 : for( sal_Int32 nA=0; nA<aAxes.getLength(); ++nA )
319 : {
320 0 : Reference< XAxis > xAxis( aAxes[nA] );
321 0 : if(!xAxis.is())
322 0 : continue;
323 :
324 0 : sal_Int32 nCooSysIndex = 0;
325 0 : sal_Int32 nDimensionIndex = 0;
326 0 : sal_Int32 nAxisIndex = 0;
327 0 : AxisHelper::getIndicesForAxis( xAxis, xDiagram, nCooSysIndex, nDimensionIndex, nAxisIndex );
328 0 : if( nAxisIndex>0 && !ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimensionCount, nDimensionIndex ) )
329 0 : continue;
330 :
331 0 : if( m_bOrderingForElementSelector )
332 : {
333 : // axis
334 0 : if( AxisHelper::isAxisVisible( xAxis ) )
335 : rContainer.push_back(
336 0 : ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( xAxis, xChartModel ) ) );
337 :
338 : // axis title
339 0 : lcl_addAxisTitle( aAxes[nA], rContainer, xChartModel );
340 : }
341 :
342 0 : Reference< beans::XPropertySet > xGridProperties( xAxis->getGridProperties() );
343 0 : if( AxisHelper::isGridVisible( xGridProperties ) )
344 : {
345 : //main grid
346 : rContainer.push_back(
347 0 : ObjectIdentifier( ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForGrid( xAxis, xChartModel ) ) ) );
348 : }
349 :
350 0 : Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() );;
351 0 : sal_Int32 nSubGrid = 0;
352 0 : for( nSubGrid = 0; nSubGrid < aSubGrids.getLength(); ++nSubGrid )
353 : {
354 0 : Reference< beans::XPropertySet > xSubGridProperties( aSubGrids[nSubGrid] );
355 0 : if( AxisHelper::isGridVisible( xSubGridProperties ) )
356 : {
357 : //sub grid
358 : rContainer.push_back(
359 0 : ObjectIdentifier( ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForGrid( xAxis, xChartModel, nSubGrid ) ) ) );
360 : }
361 0 : }
362 0 : }
363 0 : }
364 0 : }
365 :
366 0 : void ImplObjectHierarchy::createWallAndFloor(
367 : ObjectHierarchy::tChildContainer & rContainer,
368 : const Reference< XDiagram > & xDiagram )
369 : {
370 0 : sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram );
371 0 : bool bIsThreeD = ( nDimensionCount == 3 );
372 0 : bool bHasWall = DiagramHelper::isSupportingFloorAndWall( xDiagram );
373 0 : if( bHasWall && bIsThreeD )
374 : {
375 : rContainer.push_back(
376 0 : ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, OUString() ) ) );
377 :
378 0 : Reference< beans::XPropertySet > xFloor( xDiagram->getFloor());
379 0 : if( xFloor.is())
380 : rContainer.push_back(
381 0 : ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_FLOOR, OUString() ) ) );
382 : }
383 :
384 0 : }
385 :
386 0 : void ImplObjectHierarchy::createDiagramTree(
387 : ObjectHierarchy::tChildContainer & rContainer,
388 : const Reference< XChartDocument > & xChartDoc,
389 : const Reference< XDiagram > & xDiagram )
390 : {
391 0 : if( !m_bOrderingForElementSelector )
392 : {
393 0 : createDataSeriesTree( rContainer, xDiagram );
394 0 : createAxesTree( rContainer, xChartDoc, xDiagram );
395 0 : createWallAndFloor( rContainer, xDiagram );
396 : }
397 : else
398 : {
399 0 : createAxesTree( rContainer, xChartDoc, xDiagram );
400 0 : createDataSeriesTree( rContainer, xDiagram );
401 : }
402 0 : }
403 :
404 0 : void ImplObjectHierarchy::createDataSeriesTree(
405 : ObjectHierarchy::tChildContainer & rOutDiagramSubContainer,
406 : const Reference< XDiagram > & xDiagram )
407 : {
408 0 : Reference< XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW );
409 :
410 : try
411 : {
412 0 : sal_Int32 nDiagramIndex = 0;
413 0 : sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram );
414 : Sequence< Reference< XCoordinateSystem > > aCooSysSeq(
415 0 : xCooSysCnt->getCoordinateSystems());
416 0 : for( sal_Int32 nCooSysIdx=0; nCooSysIdx<aCooSysSeq.getLength(); ++nCooSysIdx )
417 : {
418 0 : Reference< XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW );
419 0 : Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes());
420 0 : for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypeSeq.getLength(); ++nCTIdx )
421 : {
422 0 : Reference< XChartType > xChartType( aChartTypeSeq[nCTIdx] );
423 0 : Reference< XDataSeriesContainer > xDSCnt( xChartType, uno::UNO_QUERY_THROW );
424 0 : Sequence< Reference< XDataSeries > > aSeriesSeq( xDSCnt->getDataSeries() );
425 : const sal_Int32 nNumberOfSeries =
426 0 : ChartTypeHelper::getNumberOfDisplayedSeries( xChartType, aSeriesSeq.getLength());
427 :
428 0 : for( sal_Int32 nSeriesIdx=0; nSeriesIdx<nNumberOfSeries; ++nSeriesIdx )
429 : {
430 : OUString aSeriesParticle(
431 : ObjectIdentifier::createParticleForSeries(
432 0 : nDiagramIndex, nCooSysIdx, nCTIdx, nSeriesIdx ));
433 : ObjectHierarchy::tOID aSeriesOID(
434 0 : ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForParticle( aSeriesParticle ) ) );
435 0 : rOutDiagramSubContainer.push_back( aSeriesOID );
436 :
437 0 : ObjectHierarchy::tChildContainer aSeriesSubContainer;
438 :
439 0 : Reference< chart2::XDataSeries > xSeries( aSeriesSeq[nSeriesIdx], uno::UNO_QUERY );
440 :
441 : // data lablels
442 0 : if( DataSeriesHelper::hasDataLabelsAtSeries( xSeries ) )
443 : {
444 0 : OUString aChildParticle( ObjectIdentifier::getStringForType( OBJECTTYPE_DATA_LABELS ) );
445 0 : aChildParticle+=("=");
446 : aSeriesSubContainer.push_back(
447 0 : ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForParticles( aSeriesParticle, aChildParticle ) ) );
448 : }
449 :
450 : // Statistics
451 0 : if( ChartTypeHelper::isSupportingStatisticProperties( xChartType, nDimensionCount ) )
452 : {
453 0 : Reference< chart2::XRegressionCurveContainer > xCurveCnt( xSeries, uno::UNO_QUERY );
454 0 : if( xCurveCnt.is())
455 : {
456 0 : Sequence< Reference< chart2::XRegressionCurve > > aCurves( xCurveCnt->getRegressionCurves());
457 0 : for( sal_Int32 nCurveIdx=0; nCurveIdx<aCurves.getLength(); ++nCurveIdx )
458 : {
459 0 : bool bIsAverageLine = RegressionCurveHelper::isMeanValueLine( aCurves[nCurveIdx] );
460 : aSeriesSubContainer.push_back(
461 0 : ObjectIdentifier( ObjectIdentifier::createDataCurveCID( aSeriesParticle, nCurveIdx, bIsAverageLine ) ) );
462 0 : if( RegressionCurveHelper::hasEquation( aCurves[nCurveIdx] ) )
463 : {
464 : aSeriesSubContainer.push_back(
465 0 : ObjectIdentifier( ObjectIdentifier::createDataCurveEquationCID( aSeriesParticle, nCurveIdx ) ) );
466 : }
467 : }
468 0 : Reference< beans::XPropertySet > xSeriesProp( xSeries, uno::UNO_QUERY );
469 0 : Reference< beans::XPropertySet > xErrorBarProp;
470 0 : if( xSeriesProp.is() &&
471 0 : (xSeriesProp->getPropertyValue( "ErrorBarY") >>= xErrorBarProp) &&
472 0 : xErrorBarProp.is())
473 : {
474 0 : sal_Int32 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE;
475 0 : if( ( xErrorBarProp->getPropertyValue( "ErrorBarStyle") >>= nStyle ) &&
476 0 : ( nStyle != ::com::sun::star::chart::ErrorBarStyle::NONE ) )
477 : {
478 : aSeriesSubContainer.push_back(
479 : ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierWithParent(
480 0 : OBJECTTYPE_DATA_ERRORS_Y, OUString(), aSeriesParticle ) ) );
481 : }
482 : }
483 :
484 0 : if( xSeriesProp.is() &&
485 0 : (xSeriesProp->getPropertyValue( "ErrorBarX") >>= xErrorBarProp) &&
486 0 : xErrorBarProp.is())
487 : {
488 0 : sal_Int32 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE;
489 0 : if( ( xErrorBarProp->getPropertyValue( "ErrorBarStyle") >>= nStyle ) &&
490 0 : ( nStyle != ::com::sun::star::chart::ErrorBarStyle::NONE ) )
491 : {
492 : aSeriesSubContainer.push_back(
493 : ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierWithParent(
494 0 : OBJECTTYPE_DATA_ERRORS_X, OUString(), aSeriesParticle ) ) );
495 : }
496 0 : }
497 0 : }
498 : }
499 :
500 : // Data Points
501 : // iterate over child shapes of legend and search for matching CIDs
502 0 : if( m_pExplicitValueProvider )
503 : {
504 : Reference< container::XIndexAccess > xSeriesShapeContainer(
505 0 : m_pExplicitValueProvider->getShapeForCID( aSeriesOID.getObjectCID() ), uno::UNO_QUERY );
506 0 : lcl_getChildOIDs( aSeriesSubContainer, xSeriesShapeContainer );
507 : }
508 :
509 0 : if( ! aSeriesSubContainer.empty())
510 0 : m_aChildMap[ aSeriesOID ] = aSeriesSubContainer;
511 0 : }
512 0 : }
513 0 : }
514 : }
515 0 : catch( const uno::Exception & ex )
516 : {
517 : ASSERT_EXCEPTION( ex );
518 0 : }
519 0 : }
520 :
521 0 : void ImplObjectHierarchy::createAdditionalShapesTree( ObjectHierarchy::tChildContainer& rContainer )
522 : {
523 : try
524 : {
525 0 : if ( m_pExplicitValueProvider )
526 : {
527 0 : Reference< drawing::XDrawPage > xDrawPage( m_pExplicitValueProvider->getDrawModelWrapper()->getMainDrawPage() );
528 0 : Reference< drawing::XShapes > xDrawPageShapes( xDrawPage, uno::UNO_QUERY_THROW );
529 0 : Reference< drawing::XShapes > xChartRoot( DrawModelWrapper::getChartRootShape( xDrawPage ) );
530 0 : sal_Int32 nCount = xDrawPageShapes->getCount();
531 0 : for ( sal_Int32 i = 0; i < nCount; ++i )
532 : {
533 0 : Reference< drawing::XShape > xShape;
534 0 : if ( xDrawPageShapes->getByIndex( i ) >>= xShape )
535 : {
536 0 : if ( xShape.is() && xShape != xChartRoot )
537 : {
538 0 : rContainer.push_back( ObjectIdentifier( xShape ) );
539 : }
540 : }
541 0 : }
542 : }
543 : }
544 0 : catch ( const uno::Exception& ex )
545 : {
546 : ASSERT_EXCEPTION( ex );
547 : }
548 0 : }
549 :
550 0 : bool ImplObjectHierarchy::hasChildren( const ObjectHierarchy::tOID& rParent )
551 : {
552 0 : if ( rParent.isValid() )
553 : {
554 0 : tChildMap::const_iterator aIt( m_aChildMap.find( rParent ));
555 0 : if( aIt != m_aChildMap.end())
556 0 : return ! (aIt->second.empty());
557 : }
558 0 : return false;
559 : }
560 :
561 0 : ObjectHierarchy::tChildContainer ImplObjectHierarchy::getChildren( const ObjectHierarchy::tOID& rParent )
562 : {
563 0 : if ( rParent.isValid() )
564 : {
565 0 : tChildMap::const_iterator aIt( m_aChildMap.find( rParent ));
566 0 : if( aIt != m_aChildMap.end())
567 0 : return aIt->second;
568 : }
569 0 : return ObjectHierarchy::tChildContainer();
570 : }
571 :
572 0 : ObjectHierarchy::tChildContainer ImplObjectHierarchy::getSiblings( const ObjectHierarchy::tOID& rNode )
573 : {
574 0 : if ( rNode.isValid() && !ObjectHierarchy::isRootNode( rNode ) )
575 : {
576 0 : for( tChildMap::const_iterator aIt( m_aChildMap.begin());
577 0 : aIt != m_aChildMap.end(); ++aIt )
578 : {
579 : ObjectHierarchy::tChildContainer::const_iterator aElemIt(
580 0 : ::std::find( aIt->second.begin(), aIt->second.end(), rNode ));
581 0 : if( aElemIt != aIt->second.end())
582 0 : return aIt->second;
583 : }
584 : }
585 0 : return ObjectHierarchy::tChildContainer();
586 : }
587 :
588 0 : ObjectHierarchy::tOID ImplObjectHierarchy::getParentImpl(
589 : const ObjectHierarchy::tOID & rParentOID,
590 : const ObjectHierarchy::tOID & rOID )
591 : {
592 : // search children
593 0 : ObjectHierarchy::tChildContainer aChildren( getChildren( rParentOID ));
594 : ObjectHierarchy::tChildContainer::const_iterator aIt(
595 0 : ::std::find( aChildren.begin(), aChildren.end(), rOID ));
596 : // recursion end
597 0 : if( aIt != aChildren.end())
598 0 : return rParentOID;
599 :
600 0 : for( aIt = aChildren.begin(); aIt != aChildren.end(); ++aIt )
601 : {
602 : // recursion
603 0 : ObjectHierarchy::tOID aTempParent( getParentImpl( *aIt, rOID ));
604 0 : if ( aTempParent.isValid() )
605 : {
606 : // exit on success
607 0 : return aTempParent;
608 : }
609 0 : }
610 :
611 : // exit on fail
612 0 : return ObjectHierarchy::tOID();
613 : }
614 :
615 0 : ObjectHierarchy::tOID ImplObjectHierarchy::getParent(
616 : const ObjectHierarchy::tOID & rOID )
617 : {
618 0 : return getParentImpl( ObjectHierarchy::getRootNodeOID(), rOID );
619 : }
620 :
621 : } // namespace impl
622 :
623 0 : ObjectHierarchy::ObjectHierarchy(
624 : const Reference< XChartDocument > & xChartDocument,
625 : ExplicitValueProvider * pExplicitValueProvider /* = 0 */,
626 : bool bFlattenDiagram /* = false */,
627 : bool bOrderingForElementSelector /* = false */) :
628 0 : m_apImpl( new impl::ImplObjectHierarchy( xChartDocument, pExplicitValueProvider, bFlattenDiagram, bOrderingForElementSelector ))
629 0 : {}
630 :
631 0 : ObjectHierarchy::~ObjectHierarchy()
632 0 : {}
633 :
634 0 : ObjectHierarchy::tOID ObjectHierarchy::getRootNodeOID()
635 : {
636 0 : return ObjectIdentifier( "ROOT" );
637 : }
638 :
639 0 : bool ObjectHierarchy::isRootNode( const ObjectHierarchy::tOID& rOID )
640 : {
641 0 : return ( rOID == ObjectHierarchy::getRootNodeOID() );
642 : }
643 :
644 0 : ObjectHierarchy::tChildContainer ObjectHierarchy::getTopLevelChildren() const
645 : {
646 0 : return m_apImpl->getChildren( ObjectHierarchy::getRootNodeOID());
647 : }
648 :
649 0 : bool ObjectHierarchy::hasChildren( const tOID& rParent ) const
650 : {
651 0 : return m_apImpl->hasChildren( rParent );
652 : }
653 :
654 0 : ObjectHierarchy::tChildContainer ObjectHierarchy::getChildren(
655 : const ObjectHierarchy::tOID& rParent ) const
656 : {
657 0 : if ( rParent.isValid() )
658 0 : return m_apImpl->getChildren( rParent );
659 :
660 0 : return ObjectHierarchy::tChildContainer();
661 : }
662 :
663 0 : ObjectHierarchy::tChildContainer ObjectHierarchy::getSiblings(
664 : const ObjectHierarchy::tOID& rNode ) const
665 : {
666 0 : if ( rNode.isValid() && !isRootNode( rNode ) )
667 0 : return m_apImpl->getSiblings( rNode );
668 :
669 0 : return ObjectHierarchy::tChildContainer();
670 : }
671 :
672 0 : ObjectHierarchy::tOID ObjectHierarchy::getParent(
673 : const ObjectHierarchy::tOID& rNode ) const
674 : {
675 0 : return m_apImpl->getParent( rNode );
676 : }
677 :
678 0 : sal_Int32 ObjectHierarchy::getIndexInParent(
679 : const ObjectHierarchy::tOID& rNode ) const
680 : {
681 0 : tOID aParentOID( m_apImpl->getParent( rNode ));
682 0 : tChildContainer aChildren( m_apImpl->getChildren( aParentOID ) );
683 0 : tChildContainer::const_iterator aIt( aChildren.begin() );
684 0 : for( sal_Int32 nIndex = 0; aIt != aChildren.end(); ++nIndex, ++aIt )
685 : {
686 0 : if ( *aIt == rNode )
687 0 : return nIndex;
688 : }
689 0 : return -1;
690 : }
691 :
692 0 : ObjectKeyNavigation::ObjectKeyNavigation(
693 : const ObjectHierarchy::tOID & rCurrentOID,
694 : const Reference< chart2::XChartDocument > & xChartDocument,
695 : ExplicitValueProvider * pExplicitValueProvider /* = 0 */ ) :
696 : m_aCurrentOID( rCurrentOID ),
697 : m_xChartDocument( xChartDocument ),
698 : m_pExplicitValueProvider( pExplicitValueProvider ),
699 0 : m_bStepDownInDiagram( true )
700 : {
701 0 : if ( !m_aCurrentOID.isValid() )
702 : {
703 0 : setCurrentSelection( ObjectHierarchy::getRootNodeOID() );
704 : }
705 0 : }
706 :
707 0 : bool ObjectKeyNavigation::handleKeyEvent(
708 : const awt::KeyEvent & rEvent )
709 : {
710 0 : bool bResult = false;
711 :
712 0 : switch( rEvent.KeyCode )
713 : {
714 : case awt::Key::TAB:
715 0 : if( rEvent.Modifiers & awt::KeyModifier::SHIFT )
716 0 : bResult = previous();
717 : else
718 0 : bResult = next();
719 0 : break;
720 : case awt::Key::HOME:
721 0 : bResult = first();
722 0 : break;
723 : case awt::Key::END:
724 0 : bResult = last();
725 0 : break;
726 : case awt::Key::F3:
727 0 : if( rEvent.Modifiers & awt::KeyModifier::SHIFT )
728 0 : bResult = up();
729 : else
730 0 : bResult = down();
731 0 : break;
732 : case awt::Key::ESCAPE:
733 0 : setCurrentSelection( ObjectIdentifier() );
734 0 : bResult = true;
735 0 : break;
736 : default:
737 0 : bResult = false;
738 0 : break;
739 : }
740 0 : return bResult;
741 : }
742 :
743 0 : void ObjectKeyNavigation::setCurrentSelection( const ObjectHierarchy::tOID& rOID )
744 : {
745 0 : m_aCurrentOID = rOID;
746 0 : }
747 :
748 0 : ObjectHierarchy::tOID ObjectKeyNavigation::getCurrentSelection() const
749 : {
750 0 : return m_aCurrentOID;
751 : }
752 :
753 0 : bool ObjectKeyNavigation::first()
754 : {
755 0 : ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
756 0 : ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection() ) );
757 0 : bool bResult = !aSiblings.empty();
758 0 : if( bResult )
759 0 : setCurrentSelection( aSiblings.front());
760 : else
761 0 : bResult = veryFirst();
762 0 : return bResult;
763 : }
764 :
765 0 : bool ObjectKeyNavigation::last()
766 : {
767 0 : ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
768 0 : ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection() ) );
769 0 : bool bResult = !aSiblings.empty();
770 0 : if( bResult )
771 0 : setCurrentSelection( aSiblings.back());
772 : else
773 0 : bResult = veryLast();
774 0 : return bResult;
775 : }
776 :
777 0 : bool ObjectKeyNavigation::next()
778 : {
779 0 : ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
780 0 : ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection() ) );
781 0 : bool bResult = !aSiblings.empty();
782 0 : if( bResult )
783 : {
784 : ObjectHierarchy::tChildContainer::const_iterator aIt(
785 0 : ::std::find( aSiblings.begin(), aSiblings.end(), getCurrentSelection()));
786 : OSL_ASSERT( aIt != aSiblings.end());
787 0 : if( ++aIt == aSiblings.end())
788 0 : aIt = aSiblings.begin();
789 0 : setCurrentSelection( *aIt );
790 : }
791 : else
792 0 : bResult = veryFirst();
793 :
794 0 : return bResult;
795 : }
796 :
797 0 : bool ObjectKeyNavigation::previous()
798 : {
799 0 : ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
800 0 : ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection()));
801 0 : bool bResult = !aSiblings.empty();
802 0 : if( bResult )
803 : {
804 : ObjectHierarchy::tChildContainer::const_iterator aIt(
805 0 : ::std::find( aSiblings.begin(), aSiblings.end(), getCurrentSelection()));
806 : OSL_ASSERT( aIt != aSiblings.end());
807 0 : if( aIt == aSiblings.begin())
808 0 : aIt = aSiblings.end();
809 0 : --aIt;
810 0 : setCurrentSelection( *aIt );
811 : }
812 : else
813 0 : bResult = veryLast();
814 0 : return bResult;
815 : }
816 :
817 0 : bool ObjectKeyNavigation::up()
818 : {
819 0 : ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
820 0 : bool bResult = !ObjectHierarchy::isRootNode( getCurrentSelection());
821 0 : if( bResult )
822 0 : setCurrentSelection( aHierarchy.getParent( getCurrentSelection()));
823 0 : return bResult;
824 : }
825 :
826 0 : bool ObjectKeyNavigation::down()
827 : {
828 0 : ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
829 0 : bool bResult = aHierarchy.hasChildren( getCurrentSelection());
830 0 : if( bResult )
831 : {
832 0 : ObjectHierarchy::tChildContainer aChildren = aHierarchy.getChildren( getCurrentSelection());
833 : OSL_ASSERT( !aChildren.empty());
834 0 : setCurrentSelection( aChildren.front());
835 : }
836 0 : return bResult;
837 : }
838 :
839 0 : bool ObjectKeyNavigation::veryFirst()
840 : {
841 0 : ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
842 0 : ObjectHierarchy::tChildContainer aChildren( aHierarchy.getTopLevelChildren());
843 0 : bool bResult = !aChildren.empty();
844 0 : if( bResult )
845 0 : setCurrentSelection( aChildren.front());
846 0 : return bResult;
847 : }
848 :
849 0 : bool ObjectKeyNavigation::veryLast()
850 : {
851 0 : ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
852 0 : ObjectHierarchy::tChildContainer aChildren( aHierarchy.getTopLevelChildren());
853 0 : bool bResult = !aChildren.empty();
854 0 : if( bResult )
855 0 : setCurrentSelection( aChildren.back());
856 0 : return bResult;
857 : }
858 :
859 : } // namespace chart
860 :
861 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|