Bump for 3.6-28
[LibreOffice.git] / chart2 / source / controller / main / ObjectHierarchy.cxx
blobf0f0dbafe83e118b11329caf636daf97e7e8f6b4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include "ObjectHierarchy.hxx"
31 #include "ObjectIdentifier.hxx"
32 #include "ChartModelHelper.hxx"
33 #include "DiagramHelper.hxx"
34 #include "RegressionCurveHelper.hxx"
35 #include "AxisHelper.hxx"
36 #include "chartview/ExplicitValueProvider.hxx"
37 #include "macros.hxx"
38 #include "LineProperties.hxx"
39 #include "ChartTypeHelper.hxx"
40 #include "DataSeriesHelper.hxx"
41 #include "LegendHelper.hxx"
42 #include "chartview/DrawModelWrapper.hxx"
44 #include <map>
45 #include <algorithm>
47 #include <com/sun/star/chart2/XTitled.hpp>
48 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
49 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
50 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
51 #include <com/sun/star/chart/ErrorBarStyle.hpp>
53 #include <com/sun/star/container/XIndexAccess.hpp>
54 #include <com/sun/star/awt/Key.hpp>
55 #include <com/sun/star/awt/KeyModifier.hpp>
57 using namespace ::com::sun::star;
58 using namespace ::com::sun::star::chart2;
60 using ::com::sun::star::uno::Reference;
61 using ::com::sun::star::uno::Sequence;
62 using ::rtl::OUString;
64 namespace
67 struct lcl_ObjectToOID : public ::std::unary_function< Reference< uno::XInterface >, ::chart::ObjectIdentifier >
69 explicit lcl_ObjectToOID( const Reference< chart2::XChartDocument > & xChartDoc ) :
70 m_xModel( xChartDoc, uno::UNO_QUERY )
73 ::chart::ObjectIdentifier operator() ( const Reference< uno::XInterface > & xObj )
75 return ::chart::ObjectIdentifier( ::chart::ObjectIdentifier::createClassifiedIdentifierForObject( xObj, m_xModel ) );
78 private:
79 Reference< frame::XModel > m_xModel;
82 void lcl_getChildOIDs(
83 ::chart::ObjectHierarchy::tChildContainer& rOutChildren,
84 const Reference< container::XIndexAccess >& xShapes )
86 if( xShapes.is())
88 sal_Int32 nCount = xShapes->getCount();
89 for( sal_Int32 i=0; i<nCount; ++i)
91 Reference< beans::XPropertySet > xShapeProp( xShapes->getByIndex( i ), uno::UNO_QUERY );
92 if( xShapeProp.is())
94 Reference< beans::XPropertySetInfo > xInfo( xShapeProp->getPropertySetInfo());
95 OUString aName;
96 if( xInfo.is() &&
97 xInfo->hasPropertyByName( C2U("Name")) &&
98 (xShapeProp->getPropertyValue( C2U("Name")) >>= aName ) &&
99 !aName.isEmpty() &&
100 ::chart::ObjectIdentifier::isCID( aName ))
102 rOutChildren.push_back( ::chart::ObjectIdentifier( aName ) );
104 Reference< container::XIndexAccess > xNewShapes( xShapeProp, uno::UNO_QUERY );
105 if( xNewShapes.is())
106 lcl_getChildOIDs( rOutChildren, xNewShapes );
112 void lcl_addAxisTitle( const Reference< XAxis >& xAxis, ::chart::ObjectHierarchy::tChildContainer& rContainer, const Reference< frame::XModel >& xChartModel )
114 Reference< XTitled > xAxisTitled( xAxis, uno::UNO_QUERY );
115 if( xAxisTitled.is())
117 Reference< XTitle > xAxisTitle( xAxisTitled->getTitleObject());
118 if( xAxisTitle.is())
119 rContainer.push_back(
120 ::chart::ObjectIdentifier( ::chart::ObjectIdentifier::createClassifiedIdentifierForObject( xAxisTitle, xChartModel ) ) );
124 } // anonymous namespace
126 namespace chart
129 namespace impl
132 class ImplObjectHierarchy
134 public:
135 explicit ImplObjectHierarchy(
136 const Reference< XChartDocument >& xChartDocument,
137 ExplicitValueProvider* pExplicitValueProvider,
138 bool bFlattenDiagram, bool bOrderingForElementSelector );
140 bool hasChildren( const ObjectHierarchy::tOID& rParent );
141 ObjectHierarchy::tChildContainer getChildren( const ObjectHierarchy::tOID& rParent );
142 ObjectHierarchy::tChildContainer getSiblings( const ObjectHierarchy::tOID& rNode );
144 ObjectHierarchy::tOID getParent( const ObjectHierarchy::tOID& rOID );
146 private:
147 void createTree( const Reference< XChartDocument > & xChartDocument );
148 void createAxesTree(
149 ObjectHierarchy::tChildContainer & rContainer,
150 const Reference< XChartDocument > & xChartDoc,
151 const Reference< XDiagram > & xDiagram );
152 void createDiagramTree(
153 ObjectHierarchy::tChildContainer& rContainer,
154 const Reference< XChartDocument >& xChartDoc,
155 const Reference< XDiagram >& xDiagram );
156 void createDataSeriesTree(
157 ObjectHierarchy::tChildContainer & rOutDiagramSubContainer,
158 const Reference< XDiagram > & xDiagram );
159 void createWallAndFloor(
160 ObjectHierarchy::tChildContainer & rContainer,
161 const Reference< XDiagram > & xDiagram );
162 void createLegendTree(
163 ObjectHierarchy::tChildContainer & rContainer,
164 const Reference< XChartDocument > & xChartDoc,
165 const Reference< XDiagram > & xDiagram );
166 void createAdditionalShapesTree( ObjectHierarchy::tChildContainer& rContainer );
168 ObjectHierarchy::tOID getParentImpl(
169 const ObjectHierarchy::tOID& rParentOID,
170 const ObjectHierarchy::tOID& rOID );
172 typedef ::std::map< ObjectHierarchy::tOID, ObjectHierarchy::tChildContainer >
173 tChildMap;
174 tChildMap m_aChildMap;
175 ExplicitValueProvider* m_pExplicitValueProvider;
176 bool m_bFlattenDiagram;
177 bool m_bOrderingForElementSelector;
180 ImplObjectHierarchy::ImplObjectHierarchy(
181 const Reference< XChartDocument >& xChartDocument,
182 ExplicitValueProvider* pExplicitValueProvider,
183 bool bFlattenDiagram,
184 bool bOrderingForElementSelector ) :
185 m_pExplicitValueProvider( pExplicitValueProvider ),
186 m_bFlattenDiagram( bFlattenDiagram ),
187 m_bOrderingForElementSelector( bOrderingForElementSelector )
189 createTree( xChartDocument );
190 // don't remember this helper to avoid access after lifetime
191 m_pExplicitValueProvider = 0;
194 void ImplObjectHierarchy::createTree( const Reference< XChartDocument >& xChartDocument )
196 m_aChildMap = tChildMap();//clear tree
198 if( !xChartDocument.is() )
199 return;
201 //@todo: change ObjectIdentifier to take an XChartDocument rather than XModel
202 Reference< frame::XModel > xModel( xChartDocument, uno::UNO_QUERY );
203 Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartDocument ) );
204 ObjectHierarchy::tOID aDiaOID;
205 if( xDiagram.is() )
206 aDiaOID = ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( xDiagram, xModel ) );
207 ObjectHierarchy::tChildContainer aTopLevelContainer;
209 // First Level
211 // Chart Area
212 if( m_bOrderingForElementSelector )
214 aTopLevelContainer.push_back( ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, OUString() ) ) );
215 if( xDiagram.is() )
217 aTopLevelContainer.push_back( aDiaOID );
218 createWallAndFloor( aTopLevelContainer, xDiagram );
219 createLegendTree( aTopLevelContainer, xChartDocument, xDiagram );
223 // Main Title
224 Reference< XTitled > xDocTitled( xChartDocument, uno::UNO_QUERY );
225 if( xDocTitled.is())
227 Reference< XTitle > xMainTitle( xDocTitled->getTitleObject());
228 if( xMainTitle.is())
229 aTopLevelContainer.push_back(
230 ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( xMainTitle, xModel ) ) );
233 if( xDiagram.is())
235 // Sub Title. Note: This is interpreted of being top level
236 Reference< XTitled > xDiaTitled( xDiagram, uno::UNO_QUERY );
237 if( xDiaTitled.is())
239 Reference< XTitle > xSubTitle( xDiaTitled->getTitleObject());
240 if( xSubTitle.is())
241 aTopLevelContainer.push_back(
242 ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( xSubTitle, xModel ) ) );
245 if( !m_bOrderingForElementSelector )
247 // Axis Titles. Note: These are interpreted of being top level
248 Sequence< Reference< XAxis > > aAxes( AxisHelper::getAllAxesOfDiagram( xDiagram ) );
249 for( sal_Int32 i=0; i<aAxes.getLength(); ++i )
250 lcl_addAxisTitle( aAxes[i], aTopLevelContainer, xModel );
252 // Diagram
253 aTopLevelContainer.push_back( aDiaOID );
256 if( m_bFlattenDiagram )
257 createDiagramTree( aTopLevelContainer, xChartDocument, xDiagram );
258 else
260 ObjectHierarchy::tChildContainer aSubContainer;
261 createDiagramTree( aSubContainer, xChartDocument, xDiagram );
262 if( !aSubContainer.empty() )
263 m_aChildMap[ aDiaOID ] = aSubContainer;
266 if( !m_bOrderingForElementSelector )
267 createLegendTree( aTopLevelContainer, xChartDocument, xDiagram );
270 // #i12587# support for shapes in chart
271 if ( !m_bOrderingForElementSelector )
273 createAdditionalShapesTree( aTopLevelContainer );
276 // Chart Area
277 if( !m_bOrderingForElementSelector )
278 aTopLevelContainer.push_back(
279 ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, OUString() ) ) );
281 if( ! aTopLevelContainer.empty())
282 m_aChildMap[ ObjectHierarchy::getRootNodeOID() ] = aTopLevelContainer;
285 void ImplObjectHierarchy::createLegendTree(
286 ObjectHierarchy::tChildContainer & rContainer,
287 const Reference< XChartDocument > & xChartDoc,
288 const Reference< XDiagram > & xDiagram )
290 if( xDiagram.is() && LegendHelper::hasLegend( xDiagram ) )
292 ObjectHierarchy::tOID aLegendOID( ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( xDiagram->getLegend(), Reference< frame::XModel >( xChartDoc, uno::UNO_QUERY ) ) ) );
293 rContainer.push_back( aLegendOID );
295 // iterate over child shapes of legend and search for matching CIDs
296 if( m_pExplicitValueProvider )
298 Reference< container::XIndexAccess > xLegendShapeContainer(
299 m_pExplicitValueProvider->getShapeForCID( aLegendOID.getObjectCID() ), uno::UNO_QUERY );
300 ObjectHierarchy::tChildContainer aLegendEntryOIDs;
301 lcl_getChildOIDs( aLegendEntryOIDs, xLegendShapeContainer );
303 m_aChildMap[ aLegendOID ] = aLegendEntryOIDs;
308 void ImplObjectHierarchy::createAxesTree(
309 ObjectHierarchy::tChildContainer & rContainer,
310 const Reference< XChartDocument > & xChartDoc,
311 const Reference< XDiagram > & xDiagram )
313 Reference< XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW );
314 sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram );
315 uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) );
316 bool bSupportsAxesGrids = ChartTypeHelper::isSupportingMainAxis( xChartType, nDimensionCount, 0 );
317 if( bSupportsAxesGrids )
319 Sequence< Reference< XAxis > > aAxes( AxisHelper::getAllAxesOfDiagram( xDiagram, /* bOnlyVisible = */ true ) );
320 if( !m_bOrderingForElementSelector )
321 ::std::transform( aAxes.getConstArray(), aAxes.getConstArray() + aAxes.getLength(),
322 ::std::back_inserter( rContainer ),
323 lcl_ObjectToOID( xChartDoc ));
325 // get all axes, also invisible ones
326 aAxes = AxisHelper::getAllAxesOfDiagram( xDiagram, /* bOnlyVisible = */ false );
327 // Grids
328 Reference< frame::XModel > xChartModel( xChartDoc, uno::UNO_QUERY );
329 for( sal_Int32 nA=0; nA<aAxes.getLength(); ++nA )
331 Reference< XAxis > xAxis( aAxes[nA] );
332 if(!xAxis.is())
333 continue;
335 sal_Int32 nCooSysIndex = 0;
336 sal_Int32 nDimensionIndex = 0;
337 sal_Int32 nAxisIndex = 0;
338 AxisHelper::getIndicesForAxis( xAxis, xDiagram, nCooSysIndex, nDimensionIndex, nAxisIndex );
339 if( nAxisIndex>0 && !ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimensionCount, nDimensionIndex ) )
340 continue;
342 if( m_bOrderingForElementSelector )
344 // axis
345 if( AxisHelper::isAxisVisible( xAxis ) )
346 rContainer.push_back(
347 ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( xAxis, xChartModel ) ) );
349 // axis title
350 lcl_addAxisTitle( aAxes[nA], rContainer, xChartModel );
353 Reference< beans::XPropertySet > xGridProperties( xAxis->getGridProperties() );
354 if( AxisHelper::isGridVisible( xGridProperties ) )
356 //main grid
357 rContainer.push_back(
358 ObjectIdentifier( ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForGrid( xAxis, xChartModel ) ) ) );
361 Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() );;
362 sal_Int32 nSubGrid = 0;
363 for( nSubGrid = 0; nSubGrid < aSubGrids.getLength(); ++nSubGrid )
365 Reference< beans::XPropertySet > xSubGridProperties( aSubGrids[nSubGrid] );
366 if( AxisHelper::isGridVisible( xSubGridProperties ) )
368 //sub grid
369 rContainer.push_back(
370 ObjectIdentifier( ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForGrid( xAxis, xChartModel, nSubGrid ) ) ) );
377 void ImplObjectHierarchy::createWallAndFloor(
378 ObjectHierarchy::tChildContainer & rContainer,
379 const Reference< XDiagram > & xDiagram )
381 sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram );
382 bool bIsThreeD = ( nDimensionCount == 3 );
383 bool bHasWall = DiagramHelper::isSupportingFloorAndWall( xDiagram );
384 if( bHasWall && bIsThreeD )
386 rContainer.push_back(
387 ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, rtl::OUString() ) ) );
389 Reference< beans::XPropertySet > xFloor( xDiagram->getFloor());
390 if( xFloor.is())
391 rContainer.push_back(
392 ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_FLOOR, rtl::OUString() ) ) );
397 void ImplObjectHierarchy::createDiagramTree(
398 ObjectHierarchy::tChildContainer & rContainer,
399 const Reference< XChartDocument > & xChartDoc,
400 const Reference< XDiagram > & xDiagram )
402 if( !m_bOrderingForElementSelector )
404 createDataSeriesTree( rContainer, xDiagram );
405 createAxesTree( rContainer, xChartDoc, xDiagram );
406 createWallAndFloor( rContainer, xDiagram );
408 else
410 createAxesTree( rContainer, xChartDoc, xDiagram );
411 createDataSeriesTree( rContainer, xDiagram );
415 void ImplObjectHierarchy::createDataSeriesTree(
416 ObjectHierarchy::tChildContainer & rOutDiagramSubContainer,
417 const Reference< XDiagram > & xDiagram )
419 Reference< XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW );
423 sal_Int32 nDiagramIndex = 0;
424 sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram );
425 Sequence< Reference< XCoordinateSystem > > aCooSysSeq(
426 xCooSysCnt->getCoordinateSystems());
427 for( sal_Int32 nCooSysIdx=0; nCooSysIdx<aCooSysSeq.getLength(); ++nCooSysIdx )
429 Reference< XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW );
430 Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes());
431 for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypeSeq.getLength(); ++nCTIdx )
433 Reference< XChartType > xChartType( aChartTypeSeq[nCTIdx] );
434 Reference< XDataSeriesContainer > xDSCnt( xChartType, uno::UNO_QUERY_THROW );
435 Sequence< Reference< XDataSeries > > aSeriesSeq( xDSCnt->getDataSeries() );
436 const sal_Int32 nNumberOfSeries =
437 ChartTypeHelper::getNumberOfDisplayedSeries( xChartType, aSeriesSeq.getLength());
439 for( sal_Int32 nSeriesIdx=0; nSeriesIdx<nNumberOfSeries; ++nSeriesIdx )
441 OUString aSeriesParticle(
442 ObjectIdentifier::createParticleForSeries(
443 nDiagramIndex, nCooSysIdx, nCTIdx, nSeriesIdx ));
444 ObjectHierarchy::tOID aSeriesOID(
445 ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForParticle( aSeriesParticle ) ) );
446 rOutDiagramSubContainer.push_back( aSeriesOID );
448 ObjectHierarchy::tChildContainer aSeriesSubContainer;
450 Reference< chart2::XDataSeries > xSeries( aSeriesSeq[nSeriesIdx], uno::UNO_QUERY );
452 // data lablels
453 if( DataSeriesHelper::hasDataLabelsAtSeries( xSeries ) )
455 rtl::OUString aChildParticle( ObjectIdentifier::getStringForType( OBJECTTYPE_DATA_LABELS ) );
456 aChildParticle+=(C2U("="));
457 aSeriesSubContainer.push_back(
458 ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForParticles( aSeriesParticle, aChildParticle ) ) );
461 // Statistics
462 if( ChartTypeHelper::isSupportingStatisticProperties( xChartType, nDimensionCount ) )
464 Reference< chart2::XRegressionCurveContainer > xCurveCnt( xSeries, uno::UNO_QUERY );
465 if( xCurveCnt.is())
467 Sequence< Reference< chart2::XRegressionCurve > > aCurves( xCurveCnt->getRegressionCurves());
468 for( sal_Int32 nCurveIdx=0; nCurveIdx<aCurves.getLength(); ++nCurveIdx )
470 bool bIsAverageLine = RegressionCurveHelper::isMeanValueLine( aCurves[nCurveIdx] );
471 aSeriesSubContainer.push_back(
472 ObjectIdentifier( ObjectIdentifier::createDataCurveCID( aSeriesParticle, nCurveIdx, bIsAverageLine ) ) );
473 if( RegressionCurveHelper::hasEquation( aCurves[nCurveIdx] ) )
475 aSeriesSubContainer.push_back(
476 ObjectIdentifier( ObjectIdentifier::createDataCurveEquationCID( aSeriesParticle, nCurveIdx ) ) );
479 Reference< beans::XPropertySet > xSeriesProp( xSeries, uno::UNO_QUERY );
480 Reference< beans::XPropertySet > xErrorBarProp;
481 if( xSeriesProp.is() &&
482 (xSeriesProp->getPropertyValue( C2U("ErrorBarY")) >>= xErrorBarProp) &&
483 xErrorBarProp.is())
485 sal_Int32 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE;
486 if( ( xErrorBarProp->getPropertyValue( C2U("ErrorBarStyle")) >>= nStyle ) &&
487 ( nStyle != ::com::sun::star::chart::ErrorBarStyle::NONE ) )
489 aSeriesSubContainer.push_back(
490 ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierWithParent(
491 OBJECTTYPE_DATA_ERRORS_Y, OUString(), aSeriesParticle ) ) );
495 if( xSeriesProp.is() &&
496 (xSeriesProp->getPropertyValue( C2U("ErrorBarX")) >>= xErrorBarProp) &&
497 xErrorBarProp.is())
499 sal_Int32 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE;
500 if( ( xErrorBarProp->getPropertyValue( C2U("ErrorBarStyle")) >>= nStyle ) &&
501 ( nStyle != ::com::sun::star::chart::ErrorBarStyle::NONE ) )
503 aSeriesSubContainer.push_back(
504 ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierWithParent(
505 OBJECTTYPE_DATA_ERRORS_X, OUString(), aSeriesParticle ) ) );
511 // Data Points
512 // iterate over child shapes of legend and search for matching CIDs
513 if( m_pExplicitValueProvider )
515 Reference< container::XIndexAccess > xSeriesShapeContainer(
516 m_pExplicitValueProvider->getShapeForCID( aSeriesOID.getObjectCID() ), uno::UNO_QUERY );
517 lcl_getChildOIDs( aSeriesSubContainer, xSeriesShapeContainer );
520 if( ! aSeriesSubContainer.empty())
521 m_aChildMap[ aSeriesOID ] = aSeriesSubContainer;
526 catch( const uno::Exception & ex )
528 ASSERT_EXCEPTION( ex );
532 void ImplObjectHierarchy::createAdditionalShapesTree( ObjectHierarchy::tChildContainer& rContainer )
536 if ( m_pExplicitValueProvider )
538 Reference< drawing::XDrawPage > xDrawPage( m_pExplicitValueProvider->getDrawModelWrapper()->getMainDrawPage() );
539 Reference< drawing::XShapes > xDrawPageShapes( xDrawPage, uno::UNO_QUERY_THROW );
540 Reference< drawing::XShapes > xChartRoot( DrawModelWrapper::getChartRootShape( xDrawPage ) );
541 sal_Int32 nCount = xDrawPageShapes->getCount();
542 for ( sal_Int32 i = 0; i < nCount; ++i )
544 Reference< drawing::XShape > xShape;
545 if ( xDrawPageShapes->getByIndex( i ) >>= xShape )
547 if ( xShape.is() && xShape != xChartRoot )
549 rContainer.push_back( ObjectIdentifier( xShape ) );
555 catch ( const uno::Exception& ex )
557 ASSERT_EXCEPTION( ex );
561 bool ImplObjectHierarchy::hasChildren( const ObjectHierarchy::tOID& rParent )
563 if ( rParent.isValid() )
565 tChildMap::const_iterator aIt( m_aChildMap.find( rParent ));
566 if( aIt != m_aChildMap.end())
567 return ! (aIt->second.empty());
569 return false;
572 ObjectHierarchy::tChildContainer ImplObjectHierarchy::getChildren( const ObjectHierarchy::tOID& rParent )
574 if ( rParent.isValid() )
576 tChildMap::const_iterator aIt( m_aChildMap.find( rParent ));
577 if( aIt != m_aChildMap.end())
578 return aIt->second;
580 return ObjectHierarchy::tChildContainer();
583 ObjectHierarchy::tChildContainer ImplObjectHierarchy::getSiblings( const ObjectHierarchy::tOID& rNode )
585 if ( rNode.isValid() && !ObjectHierarchy::isRootNode( rNode ) )
587 for( tChildMap::const_iterator aIt( m_aChildMap.begin());
588 aIt != m_aChildMap.end(); ++aIt )
590 ObjectHierarchy::tChildContainer::const_iterator aElemIt(
591 ::std::find( aIt->second.begin(), aIt->second.end(), rNode ));
592 if( aElemIt != aIt->second.end())
593 return aIt->second;
596 return ObjectHierarchy::tChildContainer();
599 ObjectHierarchy::tOID ImplObjectHierarchy::getParentImpl(
600 const ObjectHierarchy::tOID & rParentOID,
601 const ObjectHierarchy::tOID & rOID )
603 // search children
604 ObjectHierarchy::tChildContainer aChildren( getChildren( rParentOID ));
605 ObjectHierarchy::tChildContainer::const_iterator aIt(
606 ::std::find( aChildren.begin(), aChildren.end(), rOID ));
607 // recursion end
608 if( aIt != aChildren.end())
609 return rParentOID;
611 for( aIt = aChildren.begin(); aIt != aChildren.end(); ++aIt )
613 // recursion
614 ObjectHierarchy::tOID aTempParent( getParentImpl( *aIt, rOID ));
615 if ( aTempParent.isValid() )
617 // exit on success
618 return aTempParent;
622 // exit on fail
623 return ObjectHierarchy::tOID();
626 ObjectHierarchy::tOID ImplObjectHierarchy::getParent(
627 const ObjectHierarchy::tOID & rOID )
629 return getParentImpl( ObjectHierarchy::getRootNodeOID(), rOID );
632 } // namespace impl
635 ObjectHierarchy::ObjectHierarchy(
636 const Reference< XChartDocument > & xChartDocument,
637 ExplicitValueProvider * pExplicitValueProvider /* = 0 */,
638 bool bFlattenDiagram /* = false */,
639 bool bOrderingForElementSelector /* = false */) :
640 m_apImpl( new impl::ImplObjectHierarchy( xChartDocument, pExplicitValueProvider, bFlattenDiagram, bOrderingForElementSelector ))
643 ObjectHierarchy::~ObjectHierarchy()
646 ObjectHierarchy::tOID ObjectHierarchy::getRootNodeOID()
648 return ObjectIdentifier( C2U( "ROOT" ) );
651 bool ObjectHierarchy::isRootNode( const ObjectHierarchy::tOID& rOID )
653 return ( rOID == ObjectHierarchy::getRootNodeOID() );
656 ObjectHierarchy::tChildContainer ObjectHierarchy::getTopLevelChildren() const
658 return m_apImpl->getChildren( ObjectHierarchy::getRootNodeOID());
661 bool ObjectHierarchy::hasChildren( const tOID& rParent ) const
663 return m_apImpl->hasChildren( rParent );
666 ObjectHierarchy::tChildContainer ObjectHierarchy::getChildren(
667 const ObjectHierarchy::tOID& rParent ) const
669 if ( rParent.isValid() )
670 return m_apImpl->getChildren( rParent );
672 return ObjectHierarchy::tChildContainer();
675 ObjectHierarchy::tChildContainer ObjectHierarchy::getSiblings(
676 const ObjectHierarchy::tOID& rNode ) const
678 if ( rNode.isValid() && !isRootNode( rNode ) )
679 return m_apImpl->getSiblings( rNode );
681 return ObjectHierarchy::tChildContainer();
684 ObjectHierarchy::tOID ObjectHierarchy::getParent(
685 const ObjectHierarchy::tOID& rNode ) const
687 return m_apImpl->getParent( rNode );
690 sal_Int32 ObjectHierarchy::getIndexInParent(
691 const ObjectHierarchy::tOID& rNode ) const
693 tOID aParentOID( m_apImpl->getParent( rNode ));
694 tChildContainer aChildren( m_apImpl->getChildren( aParentOID ) );
695 tChildContainer::const_iterator aIt( aChildren.begin() );
696 for( sal_Int32 nIndex = 0; aIt != aChildren.end(); ++nIndex, ++aIt )
698 if ( *aIt == rNode )
699 return nIndex;
701 return -1;
704 // ================================================================================
706 ObjectKeyNavigation::ObjectKeyNavigation(
707 const ObjectHierarchy::tOID & rCurrentOID,
708 const Reference< chart2::XChartDocument > & xChartDocument,
709 ExplicitValueProvider * pExplicitValueProvider /* = 0 */ ) :
710 m_aCurrentOID( rCurrentOID ),
711 m_xChartDocument( xChartDocument ),
712 m_pExplicitValueProvider( pExplicitValueProvider ),
713 m_bStepDownInDiagram( true )
715 if ( !m_aCurrentOID.isValid() )
717 setCurrentSelection( ObjectHierarchy::getRootNodeOID() );
721 bool ObjectKeyNavigation::handleKeyEvent(
722 const awt::KeyEvent & rEvent )
724 bool bResult = false;
726 switch( rEvent.KeyCode )
728 case awt::Key::TAB:
729 if( rEvent.Modifiers & awt::KeyModifier::SHIFT )
730 bResult = previous();
731 else
732 bResult = next();
733 break;
734 case awt::Key::HOME:
735 bResult = first();
736 break;
737 case awt::Key::END:
738 bResult = last();
739 break;
740 case awt::Key::F3:
741 if( rEvent.Modifiers & awt::KeyModifier::SHIFT )
742 bResult = up();
743 else
744 bResult = down();
745 break;
746 case awt::Key::ESCAPE:
747 setCurrentSelection( ObjectIdentifier() );
748 bResult = true;
749 break;
750 default:
751 bResult = false;
752 break;
754 return bResult;
757 void ObjectKeyNavigation::setCurrentSelection( const ObjectHierarchy::tOID& rOID )
759 m_aCurrentOID = rOID;
762 ObjectHierarchy::tOID ObjectKeyNavigation::getCurrentSelection() const
764 return m_aCurrentOID;
767 bool ObjectKeyNavigation::first()
769 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
770 ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection() ) );
771 bool bResult = !aSiblings.empty();
772 if( bResult )
773 setCurrentSelection( aSiblings.front());
774 else
775 bResult = veryFirst();
776 return bResult;
779 bool ObjectKeyNavigation::last()
781 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
782 ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection() ) );
783 bool bResult = !aSiblings.empty();
784 if( bResult )
785 setCurrentSelection( aSiblings.back());
786 else
787 bResult = veryLast();
788 return bResult;
791 bool ObjectKeyNavigation::next()
793 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
794 ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection() ) );
795 bool bResult = !aSiblings.empty();
796 if( bResult )
798 ObjectHierarchy::tChildContainer::const_iterator aIt(
799 ::std::find( aSiblings.begin(), aSiblings.end(), getCurrentSelection()));
800 OSL_ASSERT( aIt != aSiblings.end());
801 if( ++aIt == aSiblings.end())
802 aIt = aSiblings.begin();
803 setCurrentSelection( *aIt );
805 else
806 bResult = veryFirst();
808 return bResult;
811 bool ObjectKeyNavigation::previous()
813 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
814 ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection()));
815 bool bResult = !aSiblings.empty();
816 if( bResult )
818 ObjectHierarchy::tChildContainer::const_iterator aIt(
819 ::std::find( aSiblings.begin(), aSiblings.end(), getCurrentSelection()));
820 OSL_ASSERT( aIt != aSiblings.end());
821 if( aIt == aSiblings.begin())
822 aIt = aSiblings.end();
823 --aIt;
824 setCurrentSelection( *aIt );
826 else
827 bResult = veryLast();
828 return bResult;
831 bool ObjectKeyNavigation::up()
833 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
834 bool bResult = !ObjectHierarchy::isRootNode( getCurrentSelection());
835 if( bResult )
836 setCurrentSelection( aHierarchy.getParent( getCurrentSelection()));
837 return bResult;
840 bool ObjectKeyNavigation::down()
842 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
843 bool bResult = aHierarchy.hasChildren( getCurrentSelection());
844 if( bResult )
846 ObjectHierarchy::tChildContainer aChildren = aHierarchy.getChildren( getCurrentSelection());
847 OSL_ASSERT( !aChildren.empty());
848 setCurrentSelection( aChildren.front());
850 return bResult;
853 bool ObjectKeyNavigation::veryFirst()
855 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
856 ObjectHierarchy::tChildContainer aChildren( aHierarchy.getTopLevelChildren());
857 bool bResult = !aChildren.empty();
858 if( bResult )
859 setCurrentSelection( aChildren.front());
860 return bResult;
863 bool ObjectKeyNavigation::veryLast()
865 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
866 ObjectHierarchy::tChildContainer aChildren( aHierarchy.getTopLevelChildren());
867 bool bResult = !aChildren.empty();
868 if( bResult )
869 setCurrentSelection( aChildren.back());
870 return bResult;
873 } // namespace chart
875 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */