fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / chart2 / source / controller / main / ObjectHierarchy.cxx
blob9f5d5ed624aea7682d3fa0adc7a5bdf6dbde9f3c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
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 #include <unonames.hxx>
35 #include <map>
36 #include <algorithm>
38 #include <com/sun/star/chart2/XTitled.hpp>
39 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
40 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
41 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
42 #include <com/sun/star/chart/ErrorBarStyle.hpp>
44 #include <com/sun/star/container/XIndexAccess.hpp>
45 #include <com/sun/star/awt/Key.hpp>
46 #include <com/sun/star/awt/KeyModifier.hpp>
48 using namespace ::com::sun::star;
49 using namespace ::com::sun::star::chart2;
51 using ::com::sun::star::uno::Reference;
52 using ::com::sun::star::uno::Sequence;
54 namespace
57 struct lcl_ObjectToOID : public ::std::unary_function< Reference< uno::XInterface >, ::chart::ObjectIdentifier >
59 explicit lcl_ObjectToOID( const Reference< chart2::XChartDocument > & xChartDoc ) :
60 m_xModel( xChartDoc, uno::UNO_QUERY )
63 ::chart::ObjectIdentifier operator() ( const Reference< uno::XInterface > & xObj )
65 return ::chart::ObjectIdentifier( ::chart::ObjectIdentifier::createClassifiedIdentifierForObject( xObj, m_xModel ) );
68 private:
69 Reference< frame::XModel > m_xModel;
72 void lcl_getChildOIDs(
73 ::chart::ObjectHierarchy::tChildContainer& rOutChildren,
74 const Reference< container::XIndexAccess >& xShapes )
76 if( xShapes.is())
78 sal_Int32 nCount = xShapes->getCount();
79 for( sal_Int32 i=0; i<nCount; ++i)
81 Reference< beans::XPropertySet > xShapeProp( xShapes->getByIndex( i ), uno::UNO_QUERY );
82 if( xShapeProp.is())
84 Reference< beans::XPropertySetInfo > xInfo( xShapeProp->getPropertySetInfo());
85 OUString aName;
86 if( xInfo.is() &&
87 xInfo->hasPropertyByName( "Name") &&
88 (xShapeProp->getPropertyValue( "Name") >>= aName ) &&
89 !aName.isEmpty() &&
90 ::chart::ObjectIdentifier::isCID( aName ))
92 rOutChildren.push_back( ::chart::ObjectIdentifier( aName ) );
94 Reference< container::XIndexAccess > xNewShapes( xShapeProp, uno::UNO_QUERY );
95 if( xNewShapes.is())
96 lcl_getChildOIDs( rOutChildren, xNewShapes );
102 void lcl_addAxisTitle( const Reference< XAxis >& xAxis, ::chart::ObjectHierarchy::tChildContainer& rContainer, const Reference< frame::XModel >& xChartModel )
104 Reference< XTitled > xAxisTitled( xAxis, uno::UNO_QUERY );
105 if( xAxisTitled.is())
107 Reference< XTitle > xAxisTitle( xAxisTitled->getTitleObject());
108 if( xAxisTitle.is())
109 rContainer.push_back(
110 ::chart::ObjectIdentifier( ::chart::ObjectIdentifier::createClassifiedIdentifierForObject( xAxisTitle, xChartModel ) ) );
114 } // anonymous namespace
116 namespace chart
119 namespace impl
122 class ImplObjectHierarchy
124 public:
125 explicit ImplObjectHierarchy(
126 const Reference< XChartDocument >& xChartDocument,
127 ExplicitValueProvider* pExplicitValueProvider,
128 bool bFlattenDiagram, bool bOrderingForElementSelector );
130 bool hasChildren( const ObjectHierarchy::tOID& rParent );
131 ObjectHierarchy::tChildContainer getChildren( const ObjectHierarchy::tOID& rParent );
132 ObjectHierarchy::tChildContainer getSiblings( const ObjectHierarchy::tOID& rNode );
134 ObjectHierarchy::tOID getParent( const ObjectHierarchy::tOID& rOID );
136 private:
137 void createTree( const Reference< XChartDocument > & xChartDocument );
138 void createAxesTree(
139 ObjectHierarchy::tChildContainer & rContainer,
140 const Reference< XChartDocument > & xChartDoc,
141 const Reference< XDiagram > & xDiagram );
142 void createDiagramTree(
143 ObjectHierarchy::tChildContainer& rContainer,
144 const Reference< XChartDocument >& xChartDoc,
145 const Reference< XDiagram >& xDiagram );
146 void createDataSeriesTree(
147 ObjectHierarchy::tChildContainer & rOutDiagramSubContainer,
148 const Reference< XDiagram > & xDiagram );
149 static void createWallAndFloor(
150 ObjectHierarchy::tChildContainer & rContainer,
151 const Reference< XDiagram > & xDiagram );
152 void createLegendTree(
153 ObjectHierarchy::tChildContainer & rContainer,
154 const Reference< XChartDocument > & xChartDoc,
155 const Reference< XDiagram > & xDiagram );
156 void createAdditionalShapesTree( ObjectHierarchy::tChildContainer& rContainer );
158 ObjectHierarchy::tOID getParentImpl(
159 const ObjectHierarchy::tOID& rParentOID,
160 const ObjectHierarchy::tOID& rOID );
162 typedef ::std::map< ObjectHierarchy::tOID, ObjectHierarchy::tChildContainer >
163 tChildMap;
164 tChildMap m_aChildMap;
165 ExplicitValueProvider* m_pExplicitValueProvider;
166 bool m_bFlattenDiagram;
167 bool m_bOrderingForElementSelector;
170 ImplObjectHierarchy::ImplObjectHierarchy(
171 const Reference< XChartDocument >& xChartDocument,
172 ExplicitValueProvider* pExplicitValueProvider,
173 bool bFlattenDiagram,
174 bool bOrderingForElementSelector ) :
175 m_pExplicitValueProvider( pExplicitValueProvider ),
176 m_bFlattenDiagram( bFlattenDiagram ),
177 m_bOrderingForElementSelector( bOrderingForElementSelector )
179 createTree( xChartDocument );
180 // don't remember this helper to avoid access after lifetime
181 m_pExplicitValueProvider = 0;
184 void ImplObjectHierarchy::createTree( const Reference< XChartDocument >& xChartDocument )
186 m_aChildMap = tChildMap();//clear tree
188 if( !xChartDocument.is() )
189 return;
191 //@todo: change ObjectIdentifier to take an XChartDocument rather than XModel
192 Reference< frame::XModel > xModel( xChartDocument, uno::UNO_QUERY );
193 Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartDocument ) );
194 ObjectHierarchy::tOID aDiaOID;
195 if( xDiagram.is() )
196 aDiaOID = ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( xDiagram, xModel ) );
197 ObjectHierarchy::tChildContainer aTopLevelContainer;
199 // First Level
201 // Chart Area
202 if( m_bOrderingForElementSelector )
204 aTopLevelContainer.push_back( ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, OUString() ) ) );
205 if( xDiagram.is() )
207 aTopLevelContainer.push_back( aDiaOID );
208 createWallAndFloor( aTopLevelContainer, xDiagram );
209 createLegendTree( aTopLevelContainer, xChartDocument, xDiagram );
213 // Main Title
214 Reference< XTitled > xDocTitled( xChartDocument, uno::UNO_QUERY );
215 if( xDocTitled.is())
217 Reference< XTitle > xMainTitle( xDocTitled->getTitleObject());
218 if( xMainTitle.is())
219 aTopLevelContainer.push_back(
220 ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( xMainTitle, xModel ) ) );
223 if( xDiagram.is())
225 // Sub Title. Note: This is interpreted of being top level
226 Reference< XTitled > xDiaTitled( xDiagram, uno::UNO_QUERY );
227 if( xDiaTitled.is())
229 Reference< XTitle > xSubTitle( xDiaTitled->getTitleObject());
230 if( xSubTitle.is())
231 aTopLevelContainer.push_back(
232 ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( xSubTitle, xModel ) ) );
235 if( !m_bOrderingForElementSelector )
237 // Axis Titles. Note: These are interpreted of being top level
238 Sequence< Reference< XAxis > > aAxes( AxisHelper::getAllAxesOfDiagram( xDiagram ) );
239 for( sal_Int32 i=0; i<aAxes.getLength(); ++i )
240 lcl_addAxisTitle( aAxes[i], aTopLevelContainer, xModel );
242 // Diagram
243 aTopLevelContainer.push_back( aDiaOID );
246 if( m_bFlattenDiagram )
247 createDiagramTree( aTopLevelContainer, xChartDocument, xDiagram );
248 else
250 ObjectHierarchy::tChildContainer aSubContainer;
251 createDiagramTree( aSubContainer, xChartDocument, xDiagram );
252 if( !aSubContainer.empty() )
253 m_aChildMap[ aDiaOID ] = aSubContainer;
256 if( !m_bOrderingForElementSelector )
257 createLegendTree( aTopLevelContainer, xChartDocument, xDiagram );
260 // #i12587# support for shapes in chart
261 if ( !m_bOrderingForElementSelector )
263 createAdditionalShapesTree( aTopLevelContainer );
266 // Chart Area
267 if( !m_bOrderingForElementSelector )
268 aTopLevelContainer.push_back(
269 ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, OUString() ) ) );
271 if( ! aTopLevelContainer.empty())
272 m_aChildMap[ ObjectHierarchy::getRootNodeOID() ] = aTopLevelContainer;
275 void ImplObjectHierarchy::createLegendTree(
276 ObjectHierarchy::tChildContainer & rContainer,
277 const Reference< XChartDocument > & xChartDoc,
278 const Reference< XDiagram > & xDiagram )
280 if( xDiagram.is() && LegendHelper::hasLegend( xDiagram ) )
282 ObjectHierarchy::tOID aLegendOID( ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( xDiagram->getLegend(), Reference< frame::XModel >( xChartDoc, uno::UNO_QUERY ) ) ) );
283 rContainer.push_back( aLegendOID );
285 // iterate over child shapes of legend and search for matching CIDs
286 if( m_pExplicitValueProvider )
288 Reference< container::XIndexAccess > xLegendShapeContainer(
289 m_pExplicitValueProvider->getShapeForCID( aLegendOID.getObjectCID() ), uno::UNO_QUERY );
290 ObjectHierarchy::tChildContainer aLegendEntryOIDs;
291 lcl_getChildOIDs( aLegendEntryOIDs, xLegendShapeContainer );
293 m_aChildMap[ aLegendOID ] = aLegendEntryOIDs;
298 void ImplObjectHierarchy::createAxesTree(
299 ObjectHierarchy::tChildContainer & rContainer,
300 const Reference< XChartDocument > & xChartDoc,
301 const Reference< XDiagram > & xDiagram )
303 Reference< XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW );
304 sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram );
305 uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) );
306 bool bSupportsAxesGrids = ChartTypeHelper::isSupportingMainAxis( xChartType, nDimensionCount, 0 );
307 if( bSupportsAxesGrids )
309 Sequence< Reference< XAxis > > aAxes( AxisHelper::getAllAxesOfDiagram( xDiagram, /* bOnlyVisible = */ true ) );
310 if( !m_bOrderingForElementSelector )
311 ::std::transform( aAxes.getConstArray(), aAxes.getConstArray() + aAxes.getLength(),
312 ::std::back_inserter( rContainer ),
313 lcl_ObjectToOID( xChartDoc ));
315 // get all axes, also invisible ones
316 aAxes = AxisHelper::getAllAxesOfDiagram( xDiagram, /* bOnlyVisible = */ false );
317 // Grids
318 Reference< frame::XModel > xChartModel( xChartDoc, uno::UNO_QUERY );
319 for( sal_Int32 nA=0; nA<aAxes.getLength(); ++nA )
321 Reference< XAxis > xAxis( aAxes[nA] );
322 if(!xAxis.is())
323 continue;
325 sal_Int32 nCooSysIndex = 0;
326 sal_Int32 nDimensionIndex = 0;
327 sal_Int32 nAxisIndex = 0;
328 AxisHelper::getIndicesForAxis( xAxis, xDiagram, nCooSysIndex, nDimensionIndex, nAxisIndex );
329 if( nAxisIndex>0 && !ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimensionCount, nDimensionIndex ) )
330 continue;
332 if( m_bOrderingForElementSelector )
334 // axis
335 if( AxisHelper::isAxisVisible( xAxis ) )
336 rContainer.push_back(
337 ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( xAxis, xChartModel ) ) );
339 // axis title
340 lcl_addAxisTitle( aAxes[nA], rContainer, xChartModel );
343 Reference< beans::XPropertySet > xGridProperties( xAxis->getGridProperties() );
344 if( AxisHelper::isGridVisible( xGridProperties ) )
346 //main grid
347 rContainer.push_back(
348 ObjectIdentifier( ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForGrid( xAxis, xChartModel ) ) ) );
351 Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() );;
352 sal_Int32 nSubGrid = 0;
353 for( nSubGrid = 0; nSubGrid < aSubGrids.getLength(); ++nSubGrid )
355 Reference< beans::XPropertySet > xSubGridProperties( aSubGrids[nSubGrid] );
356 if( AxisHelper::isGridVisible( xSubGridProperties ) )
358 //sub grid
359 rContainer.push_back(
360 ObjectIdentifier( ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForGrid( xAxis, xChartModel, nSubGrid ) ) ) );
367 void ImplObjectHierarchy::createWallAndFloor(
368 ObjectHierarchy::tChildContainer & rContainer,
369 const Reference< XDiagram > & xDiagram )
371 sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram );
372 bool bIsThreeD = ( nDimensionCount == 3 );
373 bool bHasWall = DiagramHelper::isSupportingFloorAndWall( xDiagram );
374 if( bHasWall && bIsThreeD )
376 rContainer.push_back(
377 ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, OUString() ) ) );
379 Reference< beans::XPropertySet > xFloor( xDiagram->getFloor());
380 if( xFloor.is())
381 rContainer.push_back(
382 ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_FLOOR, OUString() ) ) );
387 void ImplObjectHierarchy::createDiagramTree(
388 ObjectHierarchy::tChildContainer & rContainer,
389 const Reference< XChartDocument > & xChartDoc,
390 const Reference< XDiagram > & xDiagram )
392 if( !m_bOrderingForElementSelector )
394 createDataSeriesTree( rContainer, xDiagram );
395 createAxesTree( rContainer, xChartDoc, xDiagram );
396 createWallAndFloor( rContainer, xDiagram );
398 else
400 createAxesTree( rContainer, xChartDoc, xDiagram );
401 createDataSeriesTree( rContainer, xDiagram );
405 void ImplObjectHierarchy::createDataSeriesTree(
406 ObjectHierarchy::tChildContainer & rOutDiagramSubContainer,
407 const Reference< XDiagram > & xDiagram )
409 Reference< XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW );
413 sal_Int32 nDiagramIndex = 0;
414 sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram );
415 Sequence< Reference< XCoordinateSystem > > aCooSysSeq(
416 xCooSysCnt->getCoordinateSystems());
417 for( sal_Int32 nCooSysIdx=0; nCooSysIdx<aCooSysSeq.getLength(); ++nCooSysIdx )
419 Reference< XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW );
420 Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes());
421 for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypeSeq.getLength(); ++nCTIdx )
423 Reference< XChartType > xChartType( aChartTypeSeq[nCTIdx] );
424 Reference< XDataSeriesContainer > xDSCnt( xChartType, uno::UNO_QUERY_THROW );
425 Sequence< Reference< XDataSeries > > aSeriesSeq( xDSCnt->getDataSeries() );
426 const sal_Int32 nNumberOfSeries =
427 ChartTypeHelper::getNumberOfDisplayedSeries( xChartType, aSeriesSeq.getLength());
429 for( sal_Int32 nSeriesIdx=0; nSeriesIdx<nNumberOfSeries; ++nSeriesIdx )
431 OUString aSeriesParticle(
432 ObjectIdentifier::createParticleForSeries(
433 nDiagramIndex, nCooSysIdx, nCTIdx, nSeriesIdx ));
434 ObjectHierarchy::tOID aSeriesOID(
435 ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForParticle( aSeriesParticle ) ) );
436 rOutDiagramSubContainer.push_back( aSeriesOID );
438 ObjectHierarchy::tChildContainer aSeriesSubContainer;
440 Reference< chart2::XDataSeries > xSeries( aSeriesSeq[nSeriesIdx], uno::UNO_QUERY );
442 // data lablels
443 if( DataSeriesHelper::hasDataLabelsAtSeries( xSeries ) )
445 OUString aChildParticle( ObjectIdentifier::getStringForType( OBJECTTYPE_DATA_LABELS ) );
446 aChildParticle+=("=");
447 aSeriesSubContainer.push_back(
448 ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForParticles( aSeriesParticle, aChildParticle ) ) );
451 // Statistics
452 if( ChartTypeHelper::isSupportingStatisticProperties( xChartType, nDimensionCount ) )
454 Reference< chart2::XRegressionCurveContainer > xCurveCnt( xSeries, uno::UNO_QUERY );
455 if( xCurveCnt.is())
457 Sequence< Reference< chart2::XRegressionCurve > > aCurves( xCurveCnt->getRegressionCurves());
458 for( sal_Int32 nCurveIdx=0; nCurveIdx<aCurves.getLength(); ++nCurveIdx )
460 bool bIsAverageLine = RegressionCurveHelper::isMeanValueLine( aCurves[nCurveIdx] );
461 aSeriesSubContainer.push_back(
462 ObjectIdentifier( ObjectIdentifier::createDataCurveCID( aSeriesParticle, nCurveIdx, bIsAverageLine ) ) );
463 if( RegressionCurveHelper::hasEquation( aCurves[nCurveIdx] ) )
465 aSeriesSubContainer.push_back(
466 ObjectIdentifier( ObjectIdentifier::createDataCurveEquationCID( aSeriesParticle, nCurveIdx ) ) );
469 Reference< beans::XPropertySet > xSeriesProp( xSeries, uno::UNO_QUERY );
470 Reference< beans::XPropertySet > xErrorBarProp;
471 if( xSeriesProp.is() &&
472 (xSeriesProp->getPropertyValue( CHART_UNONAME_ERRORBAR_Y) >>= xErrorBarProp) &&
473 xErrorBarProp.is())
475 sal_Int32 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE;
476 if( ( xErrorBarProp->getPropertyValue( "ErrorBarStyle") >>= nStyle ) &&
477 ( nStyle != ::com::sun::star::chart::ErrorBarStyle::NONE ) )
479 aSeriesSubContainer.push_back(
480 ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierWithParent(
481 OBJECTTYPE_DATA_ERRORS_Y, OUString(), aSeriesParticle ) ) );
485 if( xSeriesProp.is() &&
486 (xSeriesProp->getPropertyValue(CHART_UNONAME_ERRORBAR_X) >>= xErrorBarProp) &&
487 xErrorBarProp.is())
489 sal_Int32 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE;
490 if( ( xErrorBarProp->getPropertyValue( "ErrorBarStyle") >>= nStyle ) &&
491 ( nStyle != ::com::sun::star::chart::ErrorBarStyle::NONE ) )
493 aSeriesSubContainer.push_back(
494 ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierWithParent(
495 OBJECTTYPE_DATA_ERRORS_X, OUString(), aSeriesParticle ) ) );
501 // Data Points
502 // iterate over child shapes of legend and search for matching CIDs
503 if( m_pExplicitValueProvider )
505 Reference< container::XIndexAccess > xSeriesShapeContainer(
506 m_pExplicitValueProvider->getShapeForCID( aSeriesOID.getObjectCID() ), uno::UNO_QUERY );
507 lcl_getChildOIDs( aSeriesSubContainer, xSeriesShapeContainer );
510 if( ! aSeriesSubContainer.empty())
511 m_aChildMap[ aSeriesOID ] = aSeriesSubContainer;
516 catch( const uno::Exception & ex )
518 ASSERT_EXCEPTION( ex );
522 void ImplObjectHierarchy::createAdditionalShapesTree( ObjectHierarchy::tChildContainer& rContainer )
526 if ( m_pExplicitValueProvider )
528 Reference< drawing::XDrawPage > xDrawPage( m_pExplicitValueProvider->getDrawModelWrapper()->getMainDrawPage() );
529 Reference< drawing::XShapes > xDrawPageShapes( xDrawPage, uno::UNO_QUERY_THROW );
530 Reference< drawing::XShapes > xChartRoot( DrawModelWrapper::getChartRootShape( xDrawPage ) );
531 sal_Int32 nCount = xDrawPageShapes->getCount();
532 for ( sal_Int32 i = 0; i < nCount; ++i )
534 Reference< drawing::XShape > xShape;
535 if ( xDrawPageShapes->getByIndex( i ) >>= xShape )
537 if ( xShape.is() && xShape != xChartRoot )
539 rContainer.push_back( ObjectIdentifier( xShape ) );
545 catch ( const uno::Exception& ex )
547 ASSERT_EXCEPTION( ex );
551 bool ImplObjectHierarchy::hasChildren( const ObjectHierarchy::tOID& rParent )
553 if ( rParent.isValid() )
555 tChildMap::const_iterator aIt( m_aChildMap.find( rParent ));
556 if( aIt != m_aChildMap.end())
557 return ! (aIt->second.empty());
559 return false;
562 ObjectHierarchy::tChildContainer ImplObjectHierarchy::getChildren( const ObjectHierarchy::tOID& rParent )
564 if ( rParent.isValid() )
566 tChildMap::const_iterator aIt( m_aChildMap.find( rParent ));
567 if( aIt != m_aChildMap.end())
568 return aIt->second;
570 return ObjectHierarchy::tChildContainer();
573 ObjectHierarchy::tChildContainer ImplObjectHierarchy::getSiblings( const ObjectHierarchy::tOID& rNode )
575 if ( rNode.isValid() && !ObjectHierarchy::isRootNode( rNode ) )
577 for( tChildMap::const_iterator aIt( m_aChildMap.begin());
578 aIt != m_aChildMap.end(); ++aIt )
580 ObjectHierarchy::tChildContainer::const_iterator aElemIt(
581 ::std::find( aIt->second.begin(), aIt->second.end(), rNode ));
582 if( aElemIt != aIt->second.end())
583 return aIt->second;
586 return ObjectHierarchy::tChildContainer();
589 ObjectHierarchy::tOID ImplObjectHierarchy::getParentImpl(
590 const ObjectHierarchy::tOID & rParentOID,
591 const ObjectHierarchy::tOID & rOID )
593 // search children
594 ObjectHierarchy::tChildContainer aChildren( getChildren( rParentOID ));
595 ObjectHierarchy::tChildContainer::const_iterator aIt(
596 ::std::find( aChildren.begin(), aChildren.end(), rOID ));
597 // recursion end
598 if( aIt != aChildren.end())
599 return rParentOID;
601 for( aIt = aChildren.begin(); aIt != aChildren.end(); ++aIt )
603 // recursion
604 ObjectHierarchy::tOID aTempParent( getParentImpl( *aIt, rOID ));
605 if ( aTempParent.isValid() )
607 // exit on success
608 return aTempParent;
612 // exit on fail
613 return ObjectHierarchy::tOID();
616 ObjectHierarchy::tOID ImplObjectHierarchy::getParent(
617 const ObjectHierarchy::tOID & rOID )
619 return getParentImpl( ObjectHierarchy::getRootNodeOID(), rOID );
622 } // namespace impl
624 ObjectHierarchy::ObjectHierarchy(
625 const Reference< XChartDocument > & xChartDocument,
626 ExplicitValueProvider * pExplicitValueProvider /* = 0 */,
627 bool bFlattenDiagram /* = false */,
628 bool bOrderingForElementSelector /* = false */) :
629 m_apImpl( new impl::ImplObjectHierarchy( xChartDocument, pExplicitValueProvider, bFlattenDiagram, bOrderingForElementSelector ))
632 ObjectHierarchy::~ObjectHierarchy()
635 ObjectHierarchy::tOID ObjectHierarchy::getRootNodeOID()
637 return ObjectIdentifier( "ROOT" );
640 bool ObjectHierarchy::isRootNode( const ObjectHierarchy::tOID& rOID )
642 return ( rOID == ObjectHierarchy::getRootNodeOID() );
645 ObjectHierarchy::tChildContainer ObjectHierarchy::getTopLevelChildren() const
647 return m_apImpl->getChildren( ObjectHierarchy::getRootNodeOID());
650 bool ObjectHierarchy::hasChildren( const tOID& rParent ) const
652 return m_apImpl->hasChildren( rParent );
655 ObjectHierarchy::tChildContainer ObjectHierarchy::getChildren(
656 const ObjectHierarchy::tOID& rParent ) const
658 if ( rParent.isValid() )
659 return m_apImpl->getChildren( rParent );
661 return ObjectHierarchy::tChildContainer();
664 ObjectHierarchy::tChildContainer ObjectHierarchy::getSiblings(
665 const ObjectHierarchy::tOID& rNode ) const
667 if ( rNode.isValid() && !isRootNode( rNode ) )
668 return m_apImpl->getSiblings( rNode );
670 return ObjectHierarchy::tChildContainer();
673 ObjectHierarchy::tOID ObjectHierarchy::getParent(
674 const ObjectHierarchy::tOID& rNode ) const
676 return m_apImpl->getParent( rNode );
679 sal_Int32 ObjectHierarchy::getIndexInParent(
680 const ObjectHierarchy::tOID& rNode ) const
682 tOID aParentOID( m_apImpl->getParent( rNode ));
683 tChildContainer aChildren( m_apImpl->getChildren( aParentOID ) );
684 tChildContainer::const_iterator aIt( aChildren.begin() );
685 for( sal_Int32 nIndex = 0; aIt != aChildren.end(); ++nIndex, ++aIt )
687 if ( *aIt == rNode )
688 return nIndex;
690 return -1;
693 ObjectKeyNavigation::ObjectKeyNavigation(
694 const ObjectHierarchy::tOID & rCurrentOID,
695 const Reference< chart2::XChartDocument > & xChartDocument,
696 ExplicitValueProvider * pExplicitValueProvider /* = 0 */ ) :
697 m_aCurrentOID( rCurrentOID ),
698 m_xChartDocument( xChartDocument ),
699 m_pExplicitValueProvider( pExplicitValueProvider ),
700 m_bStepDownInDiagram( true )
702 if ( !m_aCurrentOID.isValid() )
704 setCurrentSelection( ObjectHierarchy::getRootNodeOID() );
708 bool ObjectKeyNavigation::handleKeyEvent(
709 const awt::KeyEvent & rEvent )
711 bool bResult = false;
713 switch( rEvent.KeyCode )
715 case awt::Key::TAB:
716 if( rEvent.Modifiers & awt::KeyModifier::SHIFT )
717 bResult = previous();
718 else
719 bResult = next();
720 break;
721 case awt::Key::HOME:
722 bResult = first();
723 break;
724 case awt::Key::END:
725 bResult = last();
726 break;
727 case awt::Key::F3:
728 if( rEvent.Modifiers & awt::KeyModifier::SHIFT )
729 bResult = up();
730 else
731 bResult = down();
732 break;
733 case awt::Key::ESCAPE:
734 setCurrentSelection( ObjectIdentifier() );
735 bResult = true;
736 break;
737 default:
738 bResult = false;
739 break;
741 return bResult;
744 void ObjectKeyNavigation::setCurrentSelection( const ObjectHierarchy::tOID& rOID )
746 m_aCurrentOID = rOID;
749 bool ObjectKeyNavigation::first()
751 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
752 ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection() ) );
753 bool bResult = !aSiblings.empty();
754 if( bResult )
755 setCurrentSelection( aSiblings.front());
756 else
757 bResult = veryFirst();
758 return bResult;
761 bool ObjectKeyNavigation::last()
763 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
764 ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection() ) );
765 bool bResult = !aSiblings.empty();
766 if( bResult )
767 setCurrentSelection( aSiblings.back());
768 else
769 bResult = veryLast();
770 return bResult;
773 bool ObjectKeyNavigation::next()
775 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
776 ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection() ) );
777 bool bResult = !aSiblings.empty();
778 if( bResult )
780 ObjectHierarchy::tChildContainer::const_iterator aIt(
781 ::std::find( aSiblings.begin(), aSiblings.end(), getCurrentSelection()));
782 OSL_ASSERT( aIt != aSiblings.end());
783 if( ++aIt == aSiblings.end())
784 aIt = aSiblings.begin();
785 setCurrentSelection( *aIt );
787 else
788 bResult = veryFirst();
790 return bResult;
793 bool ObjectKeyNavigation::previous()
795 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
796 ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection()));
797 bool bResult = !aSiblings.empty();
798 if( bResult )
800 ObjectHierarchy::tChildContainer::const_iterator aIt(
801 ::std::find( aSiblings.begin(), aSiblings.end(), getCurrentSelection()));
802 OSL_ASSERT( aIt != aSiblings.end());
803 if( aIt == aSiblings.begin())
804 aIt = aSiblings.end();
805 --aIt;
806 setCurrentSelection( *aIt );
808 else
809 bResult = veryLast();
810 return bResult;
813 bool ObjectKeyNavigation::up()
815 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
816 bool bResult = !ObjectHierarchy::isRootNode( getCurrentSelection());
817 if( bResult )
818 setCurrentSelection( aHierarchy.getParent( getCurrentSelection()));
819 return bResult;
822 bool ObjectKeyNavigation::down()
824 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
825 bool bResult = aHierarchy.hasChildren( getCurrentSelection());
826 if( bResult )
828 ObjectHierarchy::tChildContainer aChildren = aHierarchy.getChildren( getCurrentSelection());
829 OSL_ASSERT( !aChildren.empty());
830 setCurrentSelection( aChildren.front());
832 return bResult;
835 bool ObjectKeyNavigation::veryFirst()
837 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
838 ObjectHierarchy::tChildContainer aChildren( aHierarchy.getTopLevelChildren());
839 bool bResult = !aChildren.empty();
840 if( bResult )
841 setCurrentSelection( aChildren.front());
842 return bResult;
845 bool ObjectKeyNavigation::veryLast()
847 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
848 ObjectHierarchy::tChildContainer aChildren( aHierarchy.getTopLevelChildren());
849 bool bResult = !aChildren.empty();
850 if( bResult )
851 setCurrentSelection( aChildren.back());
852 return bResult;
855 } // namespace chart
857 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */