1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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
;
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
) );
73 Reference
< frame::XModel
> m_xModel
;
76 void lcl_getChildOIDs(
77 ::chart::ObjectHierarchy::tChildContainer
& rOutChildren
,
78 const Reference
< container::XIndexAccess
>& xShapes
)
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
);
88 Reference
< beans::XPropertySetInfo
> xInfo( xShapeProp
->getPropertySetInfo());
91 xInfo
->hasPropertyByName( "Name") &&
92 (xShapeProp
->getPropertyValue( "Name") >>= aName
) &&
94 ::chart::ObjectIdentifier::isCID( aName
))
96 rOutChildren
.emplace_back( aName
);
98 Reference
< container::XIndexAccess
> xNewShapes( xShapeProp
, uno::UNO_QUERY
);
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());
113 rContainer
.emplace_back( ::chart::ObjectIdentifier::createClassifiedIdentifierForObject( xAxisTitle
, xChartModel
) );
117 } // anonymous namespace
125 class ImplObjectHierarchy
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
);
140 void createTree( const Reference
< XChartDocument
> & xChartDocument
);
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
>
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() )
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
;
199 aDiaOID
= ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( xDiagram
, xModel
) );
200 ObjectHierarchy::tChildContainer aTopLevelContainer
;
205 if( m_bOrderingForElementSelector
)
207 aTopLevelContainer
.emplace_back( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE
, OUString() ) );
210 aTopLevelContainer
.push_back( aDiaOID
);
211 createWallAndFloor( aTopLevelContainer
, xDiagram
);
212 createLegendTree( aTopLevelContainer
, xChartDocument
, xDiagram
);
217 Reference
< XTitled
> xDocTitled( xChartDocument
, uno::UNO_QUERY
);
220 Reference
< XTitle
> xMainTitle( xDocTitled
->getTitleObject());
222 aTopLevelContainer
.emplace_back( ObjectIdentifier::createClassifiedIdentifierForObject( xMainTitle
, xModel
) );
227 // Sub Title. Note: This is interpreted of being top level
228 Reference
< XTitled
> xDiaTitled( xDiagram
, uno::UNO_QUERY
);
231 Reference
< XTitle
> xSubTitle( xDiaTitled
->getTitleObject());
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
);
244 aTopLevelContainer
.push_back( aDiaOID
);
247 if( m_bFlattenDiagram
)
248 createDiagramTree( aTopLevelContainer
, xChartDocument
, xDiagram
);
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
);
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
);
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
] );
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
) )
332 if( m_bOrderingForElementSelector
)
335 if( AxisHelper::isAxisVisible( xAxis
) )
336 rContainer
.emplace_back( ObjectIdentifier::createClassifiedIdentifierForObject( xAxis
, xChartModel
) );
339 lcl_addAxisTitle( aAxes
[nA
], rContainer
, xChartModel
);
342 Reference
< beans::XPropertySet
> xGridProperties( xAxis
->getGridProperties() );
343 if( AxisHelper::isGridVisible( xGridProperties
) )
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
) )
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());
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
);
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
);
437 if( DataSeriesHelper::hasDataLabelsAtSeries( xSeries
) )
439 OUString
aChildParticle( ObjectIdentifier::getStringForType( OBJECTTYPE_DATA_LABELS
) + "=" );
440 aSeriesSubContainer
.emplace_back( ObjectIdentifier::createClassifiedIdentifierForParticles( aSeriesParticle
, aChildParticle
) );
444 if( ChartTypeHelper::isSupportingStatisticProperties( xChartType
, nDimensionCount
) )
446 Reference
< chart2::XRegressionCurveContainer
> xCurveCnt( xSeries
, uno::UNO_QUERY
);
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
) &&
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
) &&
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
) );
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());
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())
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())
573 return ObjectHierarchy::tChildContainer();
576 ObjectIdentifier
ImplObjectHierarchy::getParentImpl(
577 const ObjectIdentifier
& rParentOID
,
578 const ObjectIdentifier
& rOID
)
581 ObjectHierarchy::tChildContainer
aChildren( getChildren( rParentOID
));
582 ObjectHierarchy::tChildContainer::const_iterator
aIt(
583 std::find( aChildren
.begin(), aChildren
.end(), rOID
));
585 if( aIt
!= aChildren
.end())
588 for (auto const& child
: aChildren
)
591 ObjectIdentifier
aTempParent( getParentImpl( child
, rOID
));
592 if ( aTempParent
.isValid() )
600 return ObjectIdentifier();
603 ObjectIdentifier
ImplObjectHierarchy::getParent(
604 const ObjectIdentifier
& rOID
)
606 return getParentImpl( ObjectHierarchy::getRootNodeOID(), rOID
);
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
)
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
)
703 if( rEvent
.Modifiers
& awt::KeyModifier::SHIFT
)
704 bResult
= previous();
715 if( rEvent
.Modifiers
& awt::KeyModifier::SHIFT
)
720 case awt::Key::ESCAPE
:
721 setCurrentSelection( ObjectIdentifier() );
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();
742 setCurrentSelection( aSiblings
.front());
744 bResult
= veryFirst();
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();
754 setCurrentSelection( aSiblings
.back());
756 bResult
= veryLast();
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();
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
);
775 bResult
= veryFirst();
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();
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();
793 setCurrentSelection( *aIt
);
796 bResult
= veryLast();
800 bool ObjectKeyNavigation::up()
802 ObjectHierarchy
aHierarchy( m_xChartDocument
, m_pExplicitValueProvider
, true/*StepDownInDiagram*/ );
803 bool bResult
= !ObjectHierarchy::isRootNode( getCurrentSelection());
805 setCurrentSelection( aHierarchy
.getParent( getCurrentSelection()));
809 bool ObjectKeyNavigation::down()
811 ObjectHierarchy
aHierarchy( m_xChartDocument
, m_pExplicitValueProvider
, true/*StepDownInDiagram*/ );
812 bool bResult
= aHierarchy
.hasChildren( getCurrentSelection());
815 ObjectHierarchy::tChildContainer aChildren
= aHierarchy
.getChildren( getCurrentSelection());
816 OSL_ASSERT( !aChildren
.empty());
817 setCurrentSelection( aChildren
.front());
822 bool ObjectKeyNavigation::veryFirst()
824 ObjectHierarchy
aHierarchy( m_xChartDocument
, m_pExplicitValueProvider
, true/*StepDownInDiagram*/ );
825 ObjectHierarchy::tChildContainer
aChildren( aHierarchy
.getTopLevelChildren());
826 bool bResult
= !aChildren
.empty();
828 setCurrentSelection( aChildren
.front());
832 bool ObjectKeyNavigation::veryLast()
834 ObjectHierarchy
aHierarchy( m_xChartDocument
, m_pExplicitValueProvider
, true/*StepDownInDiagram*/ );
835 ObjectHierarchy::tChildContainer
aChildren( aHierarchy
.getTopLevelChildren());
836 bool bResult
= !aChildren
.empty();
838 setCurrentSelection( aChildren
.back());
844 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */