Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / chart2 / source / controller / main / ObjectHierarchy.cxx
blob429d9ad7e272f0f98cc892c14538d69f48b9d5da
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 <ChartTypeHelper.hxx>
28 #include <DataSeriesHelper.hxx>
29 #include <LegendHelper.hxx>
30 #include <chartview/DrawModelWrapper.hxx>
31 #include <unonames.hxx>
33 #include <map>
34 #include <algorithm>
35 #include <iterator>
37 #include <com/sun/star/drawing/XShapes.hpp>
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/chart2/XRegressionCurveContainer.hpp>
43 #include <com/sun/star/chart/ErrorBarStyle.hpp>
45 #include <com/sun/star/container/XIndexAccess.hpp>
46 #include <com/sun/star/awt/Key.hpp>
47 #include <com/sun/star/awt/KeyEvent.hpp>
48 #include <com/sun/star/awt/KeyModifier.hpp>
49 #include <com/sun/star/frame/XModel.hpp>
50 #include <tools/diagnose_ex.h>
52 using namespace ::com::sun::star;
53 using namespace ::com::sun::star::chart2;
55 using ::com::sun::star::uno::Reference;
56 using ::com::sun::star::uno::Sequence;
58 namespace
61 struct lcl_ObjectToOID
63 explicit lcl_ObjectToOID( const Reference< chart2::XChartDocument > & xChartDoc ) :
64 m_xModel( xChartDoc, uno::UNO_QUERY )
67 ::chart::ObjectIdentifier operator() ( const Reference< uno::XInterface > & xObj )
69 return ::chart::ObjectIdentifier( ::chart::ObjectIdentifier::createClassifiedIdentifierForObject( xObj, m_xModel ) );
72 private:
73 Reference< frame::XModel > m_xModel;
76 void lcl_getChildOIDs(
77 ::chart::ObjectHierarchy::tChildContainer& rOutChildren,
78 const Reference< container::XIndexAccess >& xShapes )
80 if( xShapes.is())
82 sal_Int32 nCount = xShapes->getCount();
83 for( sal_Int32 i=0; i<nCount; ++i)
85 Reference< beans::XPropertySet > xShapeProp( xShapes->getByIndex( i ), uno::UNO_QUERY );
86 if( xShapeProp.is())
88 Reference< beans::XPropertySetInfo > xInfo( xShapeProp->getPropertySetInfo());
89 OUString aName;
90 if( xInfo.is() &&
91 xInfo->hasPropertyByName( "Name") &&
92 (xShapeProp->getPropertyValue( "Name") >>= aName ) &&
93 !aName.isEmpty() &&
94 ::chart::ObjectIdentifier::isCID( aName ))
96 rOutChildren.emplace_back( aName );
98 Reference< container::XIndexAccess > xNewShapes( xShapeProp, uno::UNO_QUERY );
99 if( xNewShapes.is())
100 lcl_getChildOIDs( rOutChildren, xNewShapes );
106 void lcl_addAxisTitle( const Reference< XAxis >& xAxis, ::chart::ObjectHierarchy::tChildContainer& rContainer, const Reference< frame::XModel >& xChartModel )
108 Reference< XTitled > xAxisTitled( xAxis, uno::UNO_QUERY );
109 if( xAxisTitled.is())
111 Reference< XTitle > xAxisTitle( xAxisTitled->getTitleObject());
112 if( xAxisTitle.is())
113 rContainer.emplace_back( ::chart::ObjectIdentifier::createClassifiedIdentifierForObject( xAxisTitle, xChartModel ) );
117 } // anonymous namespace
119 namespace chart
122 namespace impl
125 class ImplObjectHierarchy
127 public:
128 explicit ImplObjectHierarchy(
129 const Reference< XChartDocument >& xChartDocument,
130 ExplicitValueProvider* pExplicitValueProvider,
131 bool bFlattenDiagram, bool bOrderingForElementSelector );
133 bool hasChildren( const ObjectIdentifier& rParent );
134 ObjectHierarchy::tChildContainer getChildren( const ObjectIdentifier& rParent );
135 ObjectHierarchy::tChildContainer getSiblings( const ObjectIdentifier& rNode );
137 ObjectIdentifier getParent( const ObjectIdentifier& rOID );
139 private:
140 void createTree( const Reference< XChartDocument > & xChartDocument );
141 void createAxesTree(
142 ObjectHierarchy::tChildContainer & rContainer,
143 const Reference< XChartDocument > & xChartDoc,
144 const Reference< XDiagram > & xDiagram );
145 void createDiagramTree(
146 ObjectHierarchy::tChildContainer& rContainer,
147 const Reference< XChartDocument >& xChartDoc,
148 const Reference< XDiagram >& xDiagram );
149 void createDataSeriesTree(
150 ObjectHierarchy::tChildContainer & rOutDiagramSubContainer,
151 const Reference< XDiagram > & xDiagram );
152 static void createWallAndFloor(
153 ObjectHierarchy::tChildContainer & rContainer,
154 const Reference< XDiagram > & xDiagram );
155 void createLegendTree(
156 ObjectHierarchy::tChildContainer & rContainer,
157 const Reference< XChartDocument > & xChartDoc,
158 const Reference< XDiagram > & xDiagram );
159 void createAdditionalShapesTree( ObjectHierarchy::tChildContainer& rContainer );
161 ObjectIdentifier getParentImpl(
162 const ObjectIdentifier& rParentOID,
163 const ObjectIdentifier& rOID );
165 typedef std::map< ObjectIdentifier, ObjectHierarchy::tChildContainer >
166 tChildMap;
167 tChildMap m_aChildMap;
168 ExplicitValueProvider* m_pExplicitValueProvider;
169 bool m_bFlattenDiagram;
170 bool m_bOrderingForElementSelector;
173 ImplObjectHierarchy::ImplObjectHierarchy(
174 const Reference< XChartDocument >& xChartDocument,
175 ExplicitValueProvider* pExplicitValueProvider,
176 bool bFlattenDiagram,
177 bool bOrderingForElementSelector ) :
178 m_pExplicitValueProvider( pExplicitValueProvider ),
179 m_bFlattenDiagram( bFlattenDiagram ),
180 m_bOrderingForElementSelector( bOrderingForElementSelector )
182 createTree( xChartDocument );
183 // don't remember this helper to avoid access after lifetime
184 m_pExplicitValueProvider = nullptr;
187 void ImplObjectHierarchy::createTree( const Reference< XChartDocument >& xChartDocument )
189 m_aChildMap = tChildMap();//clear tree
191 if( !xChartDocument.is() )
192 return;
194 //@todo: change ObjectIdentifier to take an XChartDocument rather than XModel
195 Reference< frame::XModel > xModel( xChartDocument, uno::UNO_QUERY );
196 Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartDocument ) );
197 ObjectIdentifier aDiaOID;
198 if( xDiagram.is() )
199 aDiaOID = ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( xDiagram, xModel ) );
200 ObjectHierarchy::tChildContainer aTopLevelContainer;
202 // First Level
204 // Chart Area
205 if( m_bOrderingForElementSelector )
207 aTopLevelContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, OUString() ) );
208 if( xDiagram.is() )
210 aTopLevelContainer.push_back( aDiaOID );
211 createWallAndFloor( aTopLevelContainer, xDiagram );
212 createLegendTree( aTopLevelContainer, xChartDocument, xDiagram );
216 // Main Title
217 Reference< XTitled > xDocTitled( xChartDocument, uno::UNO_QUERY );
218 if( xDocTitled.is())
220 Reference< XTitle > xMainTitle( xDocTitled->getTitleObject());
221 if( xMainTitle.is())
222 aTopLevelContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifierForObject( xMainTitle, xModel ) );
225 if( xDiagram.is())
227 // Sub Title. Note: This is interpreted of being top level
228 Reference< XTitled > xDiaTitled( xDiagram, uno::UNO_QUERY );
229 if( xDiaTitled.is())
231 Reference< XTitle > xSubTitle( xDiaTitled->getTitleObject());
232 if( xSubTitle.is())
233 aTopLevelContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifierForObject( xSubTitle, xModel ) );
236 if( !m_bOrderingForElementSelector )
238 // Axis Titles. Note: These are interpreted of being top level
239 Sequence< Reference< XAxis > > aAxes( AxisHelper::getAllAxesOfDiagram( xDiagram ) );
240 for( sal_Int32 i=0; i<aAxes.getLength(); ++i )
241 lcl_addAxisTitle( aAxes[i], aTopLevelContainer, xModel );
243 // Diagram
244 aTopLevelContainer.push_back( aDiaOID );
247 if( m_bFlattenDiagram )
248 createDiagramTree( aTopLevelContainer, xChartDocument, xDiagram );
249 else
251 ObjectHierarchy::tChildContainer aSubContainer;
252 createDiagramTree( aSubContainer, xChartDocument, xDiagram );
253 if( !aSubContainer.empty() )
254 m_aChildMap[ aDiaOID ] = aSubContainer;
257 if( !m_bOrderingForElementSelector )
258 createLegendTree( aTopLevelContainer, xChartDocument, xDiagram );
261 // #i12587# support for shapes in chart
262 if ( !m_bOrderingForElementSelector )
264 createAdditionalShapesTree( aTopLevelContainer );
267 // Chart Area
268 if( !m_bOrderingForElementSelector )
269 aTopLevelContainer.emplace_back( 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 ObjectIdentifier 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.begin(), aAxes.end(),
312 std::back_inserter( rContainer ),
313 lcl_ObjectToOID( xChartDoc ));
315 // get all axes, also invisible ones
316 aAxes = AxisHelper::getAllAxesOfDiagram( xDiagram );
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 ) )
330 continue;
332 if( m_bOrderingForElementSelector )
334 // axis
335 if( AxisHelper::isAxisVisible( xAxis ) )
336 rContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifierForObject( xAxis, xChartModel ) );
338 // axis title
339 lcl_addAxisTitle( aAxes[nA], rContainer, xChartModel );
342 Reference< beans::XPropertySet > xGridProperties( xAxis->getGridProperties() );
343 if( AxisHelper::isGridVisible( xGridProperties ) )
345 //main grid
346 rContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifierForGrid( xAxis, xChartModel ) );
349 Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() );
350 sal_Int32 nSubGrid = 0;
351 for( nSubGrid = 0; nSubGrid < aSubGrids.getLength(); ++nSubGrid )
353 Reference< beans::XPropertySet > xSubGridProperties( aSubGrids[nSubGrid] );
354 if( AxisHelper::isGridVisible( xSubGridProperties ) )
356 //sub grid
357 rContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifierForGrid( xAxis, xChartModel, nSubGrid ) );
364 void ImplObjectHierarchy::createWallAndFloor(
365 ObjectHierarchy::tChildContainer & rContainer,
366 const Reference< XDiagram > & xDiagram )
368 sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram );
369 bool bIsThreeD = ( nDimensionCount == 3 );
370 bool bHasWall = DiagramHelper::isSupportingFloorAndWall( xDiagram );
371 if( bHasWall && bIsThreeD )
373 rContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, OUString() ) );
375 Reference< beans::XPropertySet > xFloor( xDiagram->getFloor());
376 if( xFloor.is())
377 rContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_FLOOR, OUString() ) );
382 void ImplObjectHierarchy::createDiagramTree(
383 ObjectHierarchy::tChildContainer & rContainer,
384 const Reference< XChartDocument > & xChartDoc,
385 const Reference< XDiagram > & xDiagram )
387 if( !m_bOrderingForElementSelector )
389 createDataSeriesTree( rContainer, xDiagram );
390 createAxesTree( rContainer, xChartDoc, xDiagram );
391 createWallAndFloor( rContainer, xDiagram );
393 else
395 createAxesTree( rContainer, xChartDoc, xDiagram );
396 createDataSeriesTree( rContainer, xDiagram );
400 void ImplObjectHierarchy::createDataSeriesTree(
401 ObjectHierarchy::tChildContainer & rOutDiagramSubContainer,
402 const Reference< XDiagram > & xDiagram )
404 Reference< XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW );
408 sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram );
409 Sequence< Reference< XCoordinateSystem > > aCooSysSeq(
410 xCooSysCnt->getCoordinateSystems());
411 for( sal_Int32 nCooSysIdx=0; nCooSysIdx<aCooSysSeq.getLength(); ++nCooSysIdx )
413 Reference< XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW );
414 Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes());
415 for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypeSeq.getLength(); ++nCTIdx )
417 Reference< XChartType > xChartType( aChartTypeSeq[nCTIdx] );
418 Reference< XDataSeriesContainer > xDSCnt( xChartType, uno::UNO_QUERY_THROW );
419 Sequence< Reference< XDataSeries > > aSeriesSeq( xDSCnt->getDataSeries() );
420 const sal_Int32 nNumberOfSeries =
421 ChartTypeHelper::getNumberOfDisplayedSeries( xChartType, aSeriesSeq.getLength());
423 for( sal_Int32 nSeriesIdx=0; nSeriesIdx<nNumberOfSeries; ++nSeriesIdx )
425 OUString aSeriesParticle(
426 ObjectIdentifier::createParticleForSeries(
427 0, nCooSysIdx, nCTIdx, nSeriesIdx ));
428 ObjectIdentifier aSeriesOID(
429 ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForParticle( aSeriesParticle ) ) );
430 rOutDiagramSubContainer.push_back( aSeriesOID );
432 ObjectHierarchy::tChildContainer aSeriesSubContainer;
434 Reference< chart2::XDataSeries > xSeries( aSeriesSeq[nSeriesIdx], uno::UNO_QUERY );
436 // data labels
437 if( DataSeriesHelper::hasDataLabelsAtSeries( xSeries ) )
439 OUString aChildParticle( ObjectIdentifier::getStringForType( OBJECTTYPE_DATA_LABELS ) + "=" );
440 aSeriesSubContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifierForParticles( aSeriesParticle, aChildParticle ) );
443 // Statistics
444 if( ChartTypeHelper::isSupportingStatisticProperties( xChartType, nDimensionCount ) )
446 Reference< chart2::XRegressionCurveContainer > xCurveCnt( xSeries, uno::UNO_QUERY );
447 if( xCurveCnt.is())
449 Sequence< Reference< chart2::XRegressionCurve > > aCurves( xCurveCnt->getRegressionCurves());
450 for( sal_Int32 nCurveIdx=0; nCurveIdx<aCurves.getLength(); ++nCurveIdx )
452 bool bIsAverageLine = RegressionCurveHelper::isMeanValueLine( aCurves[nCurveIdx] );
453 aSeriesSubContainer.emplace_back( ObjectIdentifier::createDataCurveCID( aSeriesParticle, nCurveIdx, bIsAverageLine ) );
454 if( RegressionCurveHelper::hasEquation( aCurves[nCurveIdx] ) )
456 aSeriesSubContainer.emplace_back( ObjectIdentifier::createDataCurveEquationCID( aSeriesParticle, nCurveIdx ) );
459 Reference< beans::XPropertySet > xSeriesProp( xSeries, uno::UNO_QUERY );
460 Reference< beans::XPropertySet > xErrorBarProp;
461 if( xSeriesProp.is() &&
462 (xSeriesProp->getPropertyValue( CHART_UNONAME_ERRORBAR_Y) >>= xErrorBarProp) &&
463 xErrorBarProp.is())
465 sal_Int32 nStyle = css::chart::ErrorBarStyle::NONE;
466 if( ( xErrorBarProp->getPropertyValue( "ErrorBarStyle") >>= nStyle ) &&
467 ( nStyle != css::chart::ErrorBarStyle::NONE ) )
469 aSeriesSubContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifierWithParent(
470 OBJECTTYPE_DATA_ERRORS_Y, OUString(), aSeriesParticle ) );
474 if( xSeriesProp.is() &&
475 (xSeriesProp->getPropertyValue(CHART_UNONAME_ERRORBAR_X) >>= xErrorBarProp) &&
476 xErrorBarProp.is())
478 sal_Int32 nStyle = css::chart::ErrorBarStyle::NONE;
479 if( ( xErrorBarProp->getPropertyValue( "ErrorBarStyle") >>= nStyle ) &&
480 ( nStyle != css::chart::ErrorBarStyle::NONE ) )
482 aSeriesSubContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifierWithParent(
483 OBJECTTYPE_DATA_ERRORS_X, OUString(), aSeriesParticle ) );
489 // Data Points
490 // iterate over child shapes of legend and search for matching CIDs
491 if( m_pExplicitValueProvider )
493 Reference< container::XIndexAccess > xSeriesShapeContainer(
494 m_pExplicitValueProvider->getShapeForCID( aSeriesOID.getObjectCID() ), uno::UNO_QUERY );
495 lcl_getChildOIDs( aSeriesSubContainer, xSeriesShapeContainer );
498 if( ! aSeriesSubContainer.empty())
499 m_aChildMap[ aSeriesOID ] = aSeriesSubContainer;
504 catch( const uno::Exception & )
506 DBG_UNHANDLED_EXCEPTION("chart2");
510 void ImplObjectHierarchy::createAdditionalShapesTree( ObjectHierarchy::tChildContainer& rContainer )
514 if ( m_pExplicitValueProvider )
516 Reference< drawing::XDrawPage > xDrawPage( m_pExplicitValueProvider->getDrawModelWrapper()->getMainDrawPage() );
517 Reference< drawing::XShapes > xDrawPageShapes( xDrawPage, uno::UNO_QUERY_THROW );
518 Reference< drawing::XShapes > xChartRoot( DrawModelWrapper::getChartRootShape( xDrawPage ) );
519 sal_Int32 nCount = xDrawPageShapes->getCount();
520 for ( sal_Int32 i = 0; i < nCount; ++i )
522 Reference< drawing::XShape > xShape;
523 if ( xDrawPageShapes->getByIndex( i ) >>= xShape )
525 if ( xShape.is() && xShape != xChartRoot )
527 rContainer.emplace_back( xShape );
533 catch ( const uno::Exception& )
535 DBG_UNHANDLED_EXCEPTION("chart2");
539 bool ImplObjectHierarchy::hasChildren( const ObjectIdentifier& rParent )
541 if ( rParent.isValid() )
543 tChildMap::const_iterator aIt( m_aChildMap.find( rParent ));
544 if( aIt != m_aChildMap.end())
545 return ! (aIt->second.empty());
547 return false;
550 ObjectHierarchy::tChildContainer ImplObjectHierarchy::getChildren( const ObjectIdentifier& rParent )
552 if ( rParent.isValid() )
554 tChildMap::const_iterator aIt( m_aChildMap.find( rParent ));
555 if( aIt != m_aChildMap.end())
556 return aIt->second;
558 return ObjectHierarchy::tChildContainer();
561 ObjectHierarchy::tChildContainer ImplObjectHierarchy::getSiblings( const ObjectIdentifier& rNode )
563 if ( rNode.isValid() && !ObjectHierarchy::isRootNode( rNode ) )
565 for (auto const& child : m_aChildMap)
567 ObjectHierarchy::tChildContainer::const_iterator aElemIt(
568 std::find( child.second.begin(), child.second.end(), rNode ));
569 if( aElemIt != child.second.end())
570 return child.second;
573 return ObjectHierarchy::tChildContainer();
576 ObjectIdentifier ImplObjectHierarchy::getParentImpl(
577 const ObjectIdentifier & rParentOID,
578 const ObjectIdentifier & rOID )
580 // search children
581 ObjectHierarchy::tChildContainer aChildren( getChildren( rParentOID ));
582 ObjectHierarchy::tChildContainer::const_iterator aIt(
583 std::find( aChildren.begin(), aChildren.end(), rOID ));
584 // recursion end
585 if( aIt != aChildren.end())
586 return rParentOID;
588 for (auto const& child : aChildren)
590 // recursion
591 ObjectIdentifier aTempParent( getParentImpl( child, rOID ));
592 if ( aTempParent.isValid() )
594 // exit on success
595 return aTempParent;
599 // exit on fail
600 return ObjectIdentifier();
603 ObjectIdentifier ImplObjectHierarchy::getParent(
604 const ObjectIdentifier & rOID )
606 return getParentImpl( ObjectHierarchy::getRootNodeOID(), rOID );
609 } // namespace impl
611 ObjectHierarchy::ObjectHierarchy(
612 const Reference< XChartDocument > & xChartDocument,
613 ExplicitValueProvider * pExplicitValueProvider /* = 0 */,
614 bool bFlattenDiagram /* = false */,
615 bool bOrderingForElementSelector /* = false */) :
616 m_apImpl( new impl::ImplObjectHierarchy( xChartDocument, pExplicitValueProvider, bFlattenDiagram, bOrderingForElementSelector ))
619 ObjectHierarchy::~ObjectHierarchy()
622 ObjectIdentifier ObjectHierarchy::getRootNodeOID()
624 return ObjectIdentifier( "ROOT" );
627 bool ObjectHierarchy::isRootNode( const ObjectIdentifier& rOID )
629 return ( rOID == ObjectHierarchy::getRootNodeOID() );
632 ObjectHierarchy::tChildContainer ObjectHierarchy::getTopLevelChildren() const
634 return m_apImpl->getChildren( ObjectHierarchy::getRootNodeOID());
637 bool ObjectHierarchy::hasChildren( const ObjectIdentifier& rParent ) const
639 return m_apImpl->hasChildren( rParent );
642 ObjectHierarchy::tChildContainer ObjectHierarchy::getChildren(
643 const ObjectIdentifier& rParent ) const
645 if ( rParent.isValid() )
646 return m_apImpl->getChildren( rParent );
648 return ObjectHierarchy::tChildContainer();
651 ObjectHierarchy::tChildContainer ObjectHierarchy::getSiblings(
652 const ObjectIdentifier& rNode ) const
654 if ( rNode.isValid() && !isRootNode( rNode ) )
655 return m_apImpl->getSiblings( rNode );
657 return ObjectHierarchy::tChildContainer();
660 ObjectIdentifier ObjectHierarchy::getParent(
661 const ObjectIdentifier& rNode ) const
663 return m_apImpl->getParent( rNode );
666 sal_Int32 ObjectHierarchy::getIndexInParent(
667 const ObjectIdentifier& rNode ) const
669 ObjectIdentifier aParentOID( m_apImpl->getParent( rNode ));
670 tChildContainer aChildren( m_apImpl->getChildren( aParentOID ) );
671 sal_Int32 nIndex = 0;
672 for (auto const& child : aChildren)
674 if ( child == rNode )
675 return nIndex;
676 ++nIndex;
678 return -1;
681 ObjectKeyNavigation::ObjectKeyNavigation(
682 const ObjectIdentifier & rCurrentOID,
683 const Reference< chart2::XChartDocument > & xChartDocument,
684 ExplicitValueProvider * pExplicitValueProvider /* = 0 */ ) :
685 m_aCurrentOID( rCurrentOID ),
686 m_xChartDocument( xChartDocument ),
687 m_pExplicitValueProvider( pExplicitValueProvider )
689 if ( !m_aCurrentOID.isValid() )
691 setCurrentSelection( ObjectHierarchy::getRootNodeOID() );
695 bool ObjectKeyNavigation::handleKeyEvent(
696 const awt::KeyEvent & rEvent )
698 bool bResult = false;
700 switch( rEvent.KeyCode )
702 case awt::Key::TAB:
703 if( rEvent.Modifiers & awt::KeyModifier::SHIFT )
704 bResult = previous();
705 else
706 bResult = next();
707 break;
708 case awt::Key::HOME:
709 bResult = first();
710 break;
711 case awt::Key::END:
712 bResult = last();
713 break;
714 case awt::Key::F3:
715 if( rEvent.Modifiers & awt::KeyModifier::SHIFT )
716 bResult = up();
717 else
718 bResult = down();
719 break;
720 case awt::Key::ESCAPE:
721 setCurrentSelection( ObjectIdentifier() );
722 bResult = true;
723 break;
724 default:
725 bResult = false;
726 break;
728 return bResult;
731 void ObjectKeyNavigation::setCurrentSelection( const ObjectIdentifier& rOID )
733 m_aCurrentOID = rOID;
736 bool ObjectKeyNavigation::first()
738 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, true/*StepDownInDiagram*/ );
739 ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection() ) );
740 bool bResult = !aSiblings.empty();
741 if( bResult )
742 setCurrentSelection( aSiblings.front());
743 else
744 bResult = veryFirst();
745 return bResult;
748 bool ObjectKeyNavigation::last()
750 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, true/*StepDownInDiagram*/ );
751 ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection() ) );
752 bool bResult = !aSiblings.empty();
753 if( bResult )
754 setCurrentSelection( aSiblings.back());
755 else
756 bResult = veryLast();
757 return bResult;
760 bool ObjectKeyNavigation::next()
762 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, true/*StepDownInDiagram*/ );
763 ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection() ) );
764 bool bResult = !aSiblings.empty();
765 if( bResult )
767 ObjectHierarchy::tChildContainer::const_iterator aIt(
768 std::find( aSiblings.begin(), aSiblings.end(), getCurrentSelection()));
769 assert(aIt != aSiblings.end());
770 if( ++aIt == aSiblings.end())
771 aIt = aSiblings.begin();
772 setCurrentSelection( *aIt );
774 else
775 bResult = veryFirst();
777 return bResult;
780 bool ObjectKeyNavigation::previous()
782 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, true/*StepDownInDiagram*/ );
783 ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection()));
784 bool bResult = !aSiblings.empty();
785 if( bResult )
787 ObjectHierarchy::tChildContainer::const_iterator aIt(
788 std::find( aSiblings.begin(), aSiblings.end(), getCurrentSelection()));
789 OSL_ASSERT( aIt != aSiblings.end());
790 if( aIt == aSiblings.begin())
791 aIt = aSiblings.end();
792 --aIt;
793 setCurrentSelection( *aIt );
795 else
796 bResult = veryLast();
797 return bResult;
800 bool ObjectKeyNavigation::up()
802 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, true/*StepDownInDiagram*/ );
803 bool bResult = !ObjectHierarchy::isRootNode( getCurrentSelection());
804 if( bResult )
805 setCurrentSelection( aHierarchy.getParent( getCurrentSelection()));
806 return bResult;
809 bool ObjectKeyNavigation::down()
811 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, true/*StepDownInDiagram*/ );
812 bool bResult = aHierarchy.hasChildren( getCurrentSelection());
813 if( bResult )
815 ObjectHierarchy::tChildContainer aChildren = aHierarchy.getChildren( getCurrentSelection());
816 OSL_ASSERT( !aChildren.empty());
817 setCurrentSelection( aChildren.front());
819 return bResult;
822 bool ObjectKeyNavigation::veryFirst()
824 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, true/*StepDownInDiagram*/ );
825 ObjectHierarchy::tChildContainer aChildren( aHierarchy.getTopLevelChildren());
826 bool bResult = !aChildren.empty();
827 if( bResult )
828 setCurrentSelection( aChildren.front());
829 return bResult;
832 bool ObjectKeyNavigation::veryLast()
834 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, true/*StepDownInDiagram*/ );
835 ObjectHierarchy::tChildContainer aChildren( aHierarchy.getTopLevelChildren());
836 bool bResult = !aChildren.empty();
837 if( bResult )
838 setCurrentSelection( aChildren.back());
839 return bResult;
842 } // namespace chart
844 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */