merge the formfield patch from ooo-build
[ooovba.git] / chart2 / source / controller / main / ObjectHierarchy.cxx
blobcbc85ce381ec07a358972aece3de8fb1076e92f3
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ObjectHierarchy.cxx,v $
10 * $Revision: 1.7 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_chart2.hxx"
34 #include "ObjectHierarchy.hxx"
35 #include "ObjectIdentifier.hxx"
36 #include "ChartModelHelper.hxx"
37 #include "DiagramHelper.hxx"
38 #include "RegressionCurveHelper.hxx"
39 #include "AxisHelper.hxx"
40 #include "chartview/ExplicitValueProvider.hxx"
41 #include "macros.hxx"
42 #include "LineProperties.hxx"
43 #include "ChartTypeHelper.hxx"
44 #include "DataSeriesHelper.hxx"
45 #include "LegendHelper.hxx"
47 #include <map>
48 #include <algorithm>
50 #include <com/sun/star/chart2/XTitled.hpp>
51 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
52 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
53 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
54 #include <com/sun/star/chart/ErrorBarStyle.hpp>
56 #include <com/sun/star/container/XIndexAccess.hpp>
57 #include <com/sun/star/awt/Key.hpp>
58 #include <com/sun/star/awt/KeyModifier.hpp>
60 using namespace ::com::sun::star;
61 using namespace ::com::sun::star::chart2;
63 using ::com::sun::star::uno::Reference;
64 using ::com::sun::star::uno::Sequence;
65 using ::rtl::OUString;
67 namespace
69 struct lcl_ObjectToCID : public ::std::unary_function< Reference< uno::XInterface >, OUString >
71 explicit lcl_ObjectToCID( const Reference< chart2::XChartDocument > & xChartDoc ) :
72 m_xModel( xChartDoc, uno::UNO_QUERY )
75 OUString operator() ( const Reference< uno::XInterface > & xObj )
77 return ::chart::ObjectIdentifier::createClassifiedIdentifierForObject( xObj, m_xModel );
80 private:
81 Reference< frame::XModel > m_xModel;
84 void lcl_getChildCIDs(
85 ::chart::ObjectHierarchy::tChildContainer & rOutChildren,
86 const Reference< container::XIndexAccess > & xShapes )
88 if( xShapes.is())
90 sal_Int32 nCount = xShapes->getCount();
91 for( sal_Int32 i=0; i<nCount; ++i)
93 Reference< beans::XPropertySet > xShapeProp( xShapes->getByIndex( i ), uno::UNO_QUERY );
94 if( xShapeProp.is())
96 Reference< beans::XPropertySetInfo > xInfo( xShapeProp->getPropertySetInfo());
97 OUString aName;
98 if( xInfo.is() &&
99 xInfo->hasPropertyByName( C2U("Name")) &&
100 (xShapeProp->getPropertyValue( C2U("Name")) >>= aName ) &&
101 aName.getLength() > 0 &&
102 ::chart::ObjectIdentifier::isCID( aName ))
104 rOutChildren.push_back( aName );
106 Reference< container::XIndexAccess > xNewShapes( xShapeProp, uno::UNO_QUERY );
107 if( xNewShapes.is())
108 lcl_getChildCIDs( rOutChildren, xNewShapes );
114 void lcl_addAxisTitle( const Reference< XAxis >& xAxis, ::chart::ObjectHierarchy::tChildContainer& rContainer, const Reference< frame::XModel >& xChartModel )
116 Reference< XTitled > xAxisTitled( xAxis, uno::UNO_QUERY );
117 if( xAxisTitled.is())
119 Reference< XTitle > xAxisTitle( xAxisTitled->getTitleObject());
120 if( xAxisTitle.is())
121 rContainer.push_back(
122 ::chart::ObjectIdentifier::createClassifiedIdentifierForObject( xAxisTitle, xChartModel ));
126 } // anonymous namespace
129 namespace chart
132 namespace impl
134 class ImplObjectHierarchy
136 public:
137 explicit ImplObjectHierarchy(
138 const Reference< XChartDocument > & xChartDocument,
139 ExplicitValueProvider * pExplicitValueProvider,
140 bool bFlattenDiagram, bool bOrderingForElementSelector );
142 bool hasChildren( const OUString & rParent );
143 ObjectHierarchy::tChildContainer getChildren( const OUString & rParent );
144 ObjectHierarchy::tChildContainer getSiblings( const OUString & rNode );
146 ObjectHierarchy::tCID getParent( const ObjectHierarchy::tCID & rCID );
148 private:
149 void createTree( const Reference< XChartDocument > & xChartDocument );
150 void createAxesTree(
151 ObjectHierarchy::tChildContainer & rContainer,
152 const Reference< XChartDocument > & xChartDoc,
153 const Reference< XDiagram > & xDiagram );
154 void createDiagramTree(
155 ObjectHierarchy::tChildContainer & rContainer,
156 const Reference< XChartDocument > & xChartDoc,
157 const Reference< XDiagram > & xDiagram );
158 void createDataSeriesTree(
159 ObjectHierarchy::tChildContainer & rOutDiagramSubContainer,
160 const Reference< XDiagram > & xDiagram );
161 void createWallAndFloor(
162 ObjectHierarchy::tChildContainer & rContainer,
163 const Reference< XDiagram > & xDiagram );
164 void createLegendTree(
165 ObjectHierarchy::tChildContainer & rContainer,
166 const Reference< XChartDocument > & xChartDoc,
167 const Reference< XDiagram > & xDiagram );
169 ObjectHierarchy::tCID getParentImpl(
170 const ObjectHierarchy::tCID & rParentCID,
171 const ObjectHierarchy::tCID & rCID );
173 typedef ::std::map< OUString, ObjectHierarchy::tChildContainer >
174 tChildMap;
175 tChildMap m_aChildMap;
176 ExplicitValueProvider * m_pExplicitValueProvider;
177 bool m_bFlattenDiagram;
178 bool m_bOrderingForElementSelector;
181 ImplObjectHierarchy::ImplObjectHierarchy(
182 const Reference< XChartDocument > & xChartDocument,
183 ExplicitValueProvider * pExplicitValueProvider,
184 bool bFlattenDiagram,
185 bool bOrderingForElementSelector ) :
186 m_pExplicitValueProvider( pExplicitValueProvider ),
187 m_bFlattenDiagram( bFlattenDiagram ),
188 m_bOrderingForElementSelector( bOrderingForElementSelector )
190 createTree( xChartDocument );
191 // don't remember this helper to avoid access after lifetime
192 m_pExplicitValueProvider = 0;
195 void ImplObjectHierarchy::createTree( const Reference< XChartDocument > & xChartDocument )
197 if( !xChartDocument.is())
198 return;
200 //@todo: change ObjectIdentifier to take an XChartDocument rather than XModel
201 Reference< frame::XModel > xModel( xChartDocument, uno::UNO_QUERY );
202 Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartDocument ) );
203 OUString aDiaCID( ObjectIdentifier::createClassifiedIdentifierForObject( xDiagram, xModel ));
204 ObjectHierarchy::tChildContainer aTopLevelContainer;
206 // First Level
208 // Chart Area
209 if( m_bOrderingForElementSelector )
211 aTopLevelContainer.push_back( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, OUString() ) );
212 aTopLevelContainer.push_back( aDiaCID );
213 createWallAndFloor( aTopLevelContainer, xDiagram );
214 createLegendTree( aTopLevelContainer, xChartDocument, xDiagram );
217 // Main Title
218 Reference< XTitled > xDocTitled( xChartDocument, uno::UNO_QUERY );
219 if( xDocTitled.is())
221 Reference< XTitle > xMainTitle( xDocTitled->getTitleObject());
222 if( xMainTitle.is())
223 aTopLevelContainer.push_back(
224 ObjectIdentifier::createClassifiedIdentifierForObject( xMainTitle, xModel ));
227 if( xDiagram.is())
229 // Sub Title. Note: This is interpreted of being top level
230 Reference< XTitled > xDiaTitled( xDiagram, uno::UNO_QUERY );
231 if( xDiaTitled.is())
233 Reference< XTitle > xSubTitle( xDiaTitled->getTitleObject());
234 if( xSubTitle.is())
235 aTopLevelContainer.push_back(
236 ObjectIdentifier::createClassifiedIdentifierForObject( xSubTitle, xModel ));
239 if( !m_bOrderingForElementSelector )
241 // Axis Titles. Note: These are interpreted of being top level
242 Sequence< Reference< XAxis > > aAxes( AxisHelper::getAllAxesOfDiagram( xDiagram ) );
243 for( sal_Int32 i=0; i<aAxes.getLength(); ++i )
244 lcl_addAxisTitle( aAxes[i], aTopLevelContainer, xModel );
246 // Diagram
247 aTopLevelContainer.push_back( aDiaCID );
250 if( m_bFlattenDiagram )
251 createDiagramTree( aTopLevelContainer, xChartDocument, xDiagram );
252 else
254 ObjectHierarchy::tChildContainer aSubContainer;
255 createDiagramTree( aSubContainer, xChartDocument, xDiagram );
256 if( ! aSubContainer.empty())
257 m_aChildMap[ aDiaCID ] = aSubContainer;
260 if( !m_bOrderingForElementSelector )
261 createLegendTree( aTopLevelContainer, xChartDocument, xDiagram );
264 // Chart Area
265 if( !m_bOrderingForElementSelector )
266 aTopLevelContainer.push_back(
267 ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, OUString() ) );
269 if( ! aTopLevelContainer.empty())
270 m_aChildMap[ ObjectHierarchy::getRootNodeCID() ] = aTopLevelContainer;
273 void ImplObjectHierarchy::createLegendTree(
274 ObjectHierarchy::tChildContainer & rContainer,
275 const Reference< XChartDocument > & xChartDoc,
276 const Reference< XDiagram > & xDiagram )
278 if( xDiagram.is() && LegendHelper::hasLegend( xDiagram ) )
280 OUString aLegendCID( ObjectIdentifier::createClassifiedIdentifierForObject( xDiagram->getLegend(), Reference< frame::XModel >( xChartDoc, uno::UNO_QUERY ) ));
281 rContainer.push_back( aLegendCID );
283 // iterate over child shapes of legend and search for matching CIDs
284 if( m_pExplicitValueProvider )
286 Reference< container::XIndexAccess > xLegendShapeContainer(
287 m_pExplicitValueProvider->getShapeForCID( aLegendCID ), uno::UNO_QUERY );
288 ObjectHierarchy::tChildContainer aLegendEntryCIDs;
289 lcl_getChildCIDs( aLegendEntryCIDs, xLegendShapeContainer );
291 m_aChildMap[ aLegendCID ] = aLegendEntryCIDs;
296 void ImplObjectHierarchy::createAxesTree(
297 ObjectHierarchy::tChildContainer & rContainer,
298 const Reference< XChartDocument > & xChartDoc,
299 const Reference< XDiagram > & xDiagram )
301 Reference< XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW );
302 sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram );
303 uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) );
304 bool bSupportsAxesGrids = ChartTypeHelper::isSupportingMainAxis( xChartType, nDimensionCount, 0 );
305 if( bSupportsAxesGrids )
307 Sequence< Reference< XAxis > > aAxes( AxisHelper::getAllAxesOfDiagram( xDiagram, /* bOnlyVisible = */ true ) );
308 if( !m_bOrderingForElementSelector )
309 ::std::transform( aAxes.getConstArray(), aAxes.getConstArray() + aAxes.getLength(),
310 ::std::back_inserter( rContainer ),
311 lcl_ObjectToCID( xChartDoc ));
313 // get all axes, also invisible ones
314 aAxes = AxisHelper::getAllAxesOfDiagram( xDiagram, /* bOnlyVisible = */ false );
315 // Grids
316 Reference< frame::XModel > xChartModel( xChartDoc, uno::UNO_QUERY );
317 for( sal_Int32 nA=0; nA<aAxes.getLength(); ++nA )
319 Reference< XAxis > xAxis( aAxes[nA] );
320 if(!xAxis.is())
321 continue;
323 sal_Int32 nCooSysIndex = 0;
324 sal_Int32 nDimensionIndex = 0;
325 sal_Int32 nAxisIndex = 0;
326 AxisHelper::getIndicesForAxis( xAxis, xDiagram, nCooSysIndex, nDimensionIndex, nAxisIndex );
327 if( nAxisIndex>0 && !ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimensionCount, nDimensionIndex ) )
328 continue;
330 if( m_bOrderingForElementSelector )
332 // axis
333 if( AxisHelper::isAxisVisible( xAxis ) )
334 rContainer.push_back(
335 ObjectIdentifier::createClassifiedIdentifierForObject( xAxis, xChartModel ) );
337 // axis title
338 lcl_addAxisTitle( aAxes[nA], rContainer, xChartModel );
341 Reference< beans::XPropertySet > xGridProperties( xAxis->getGridProperties() );
342 if( AxisHelper::isGridVisible( xGridProperties ) )
344 //main grid
345 rContainer.push_back(
346 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.push_back(
358 ObjectIdentifier::createClassifiedIdentifierForGrid( xAxis, xChartModel, nSubGrid ) );
365 void ImplObjectHierarchy::createWallAndFloor(
366 ObjectHierarchy::tChildContainer & rContainer,
367 const Reference< XDiagram > & xDiagram )
369 sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram );
370 bool bIsThreeD = ( nDimensionCount == 3 );
371 bool bHasWall = DiagramHelper::isSupportingFloorAndWall( xDiagram );
372 if( bHasWall && bIsThreeD )
374 rContainer.push_back(
375 ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, rtl::OUString()));
377 Reference< beans::XPropertySet > xFloor( xDiagram->getFloor());
378 if( xFloor.is())
379 rContainer.push_back(
380 ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_FLOOR, rtl::OUString()));
385 void ImplObjectHierarchy::createDiagramTree(
386 ObjectHierarchy::tChildContainer & rContainer,
387 const Reference< XChartDocument > & xChartDoc,
388 const Reference< XDiagram > & xDiagram )
390 if( !m_bOrderingForElementSelector )
392 createDataSeriesTree( rContainer, xDiagram );
393 createAxesTree( rContainer, xChartDoc, xDiagram );
394 createWallAndFloor( rContainer, xDiagram );
396 else
398 createAxesTree( rContainer, xChartDoc, xDiagram );
399 createDataSeriesTree( rContainer, xDiagram );
403 void ImplObjectHierarchy::createDataSeriesTree(
404 ObjectHierarchy::tChildContainer & rOutDiagramSubContainer,
405 const Reference< XDiagram > & xDiagram )
407 Reference< XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW );
411 sal_Int32 nDiagramIndex = 0;
412 sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram );
413 Sequence< Reference< XCoordinateSystem > > aCooSysSeq(
414 xCooSysCnt->getCoordinateSystems());
415 for( sal_Int32 nCooSysIdx=0; nCooSysIdx<aCooSysSeq.getLength(); ++nCooSysIdx )
417 Reference< XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW );
418 Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes());
419 for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypeSeq.getLength(); ++nCTIdx )
421 Reference< XChartType > xChartType( aChartTypeSeq[nCTIdx] );
422 Reference< XDataSeriesContainer > xDSCnt( xChartType, uno::UNO_QUERY_THROW );
423 Sequence< Reference< XDataSeries > > aSeriesSeq( xDSCnt->getDataSeries() );
424 const sal_Int32 nNumberOfSeries =
425 ChartTypeHelper::getNumberOfDisplayedSeries( xChartType, aSeriesSeq.getLength());
427 for( sal_Int32 nSeriesIdx=0; nSeriesIdx<nNumberOfSeries; ++nSeriesIdx )
429 OUString aSeriesParticle(
430 ObjectIdentifier::createParticleForSeries(
431 nDiagramIndex, nCooSysIdx, nCTIdx, nSeriesIdx ));
432 ObjectHierarchy::tCID aSeriesCID(
433 ObjectIdentifier::createClassifiedIdentifierForParticle( aSeriesParticle ));
434 rOutDiagramSubContainer.push_back( aSeriesCID );
436 ObjectHierarchy::tChildContainer aSeriesSubContainer;
438 Reference< chart2::XDataSeries > xSeries( aSeriesSeq[nSeriesIdx], uno::UNO_QUERY );
440 // data lablels
441 if( DataSeriesHelper::hasDataLabelsAtSeries( xSeries ) )
443 rtl::OUString aChildParticle( ObjectIdentifier::getStringForType( OBJECTTYPE_DATA_LABELS ) );
444 aChildParticle+=(C2U("="));
445 aSeriesSubContainer.push_back(
446 ObjectIdentifier::createClassifiedIdentifierForParticles( aSeriesParticle, aChildParticle ));
449 // Statistics
450 if( ChartTypeHelper::isSupportingStatisticProperties( xChartType, nDimensionCount ) )
452 Reference< chart2::XRegressionCurveContainer > xCurveCnt( xSeries, uno::UNO_QUERY );
453 if( xCurveCnt.is())
455 Sequence< Reference< chart2::XRegressionCurve > > aCurves( xCurveCnt->getRegressionCurves());
456 for( sal_Int32 nCurveIdx=0; nCurveIdx<aCurves.getLength(); ++nCurveIdx )
458 bool bIsAverageLine = RegressionCurveHelper::isMeanValueLine( aCurves[nCurveIdx] );
459 aSeriesSubContainer.push_back(
460 ObjectIdentifier::createDataCurveCID( aSeriesParticle, nCurveIdx, bIsAverageLine ));
461 if( RegressionCurveHelper::hasEquation( aCurves[nCurveIdx] ) )
463 aSeriesSubContainer.push_back(
464 ObjectIdentifier::createDataCurveEquationCID( aSeriesParticle, nCurveIdx ));
467 Reference< beans::XPropertySet > xSeriesProp( xSeries, uno::UNO_QUERY );
468 Reference< beans::XPropertySet > xErrorBarProp;
469 if( xSeriesProp.is() &&
470 (xSeriesProp->getPropertyValue( C2U("ErrorBarY")) >>= xErrorBarProp) &&
471 xErrorBarProp.is())
473 sal_Int32 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE;
474 if( ( xErrorBarProp->getPropertyValue( C2U("ErrorBarStyle")) >>= nStyle ) &&
475 ( nStyle != ::com::sun::star::chart::ErrorBarStyle::NONE ) )
477 aSeriesSubContainer.push_back(
478 ObjectIdentifier::createClassifiedIdentifierWithParent(
479 OBJECTTYPE_DATA_ERRORS, OUString(), aSeriesParticle ));
485 // Data Points
486 // iterate over child shapes of legend and search for matching CIDs
487 if( m_pExplicitValueProvider )
489 Reference< container::XIndexAccess > xSeriesShapeContainer(
490 m_pExplicitValueProvider->getShapeForCID( aSeriesCID ), uno::UNO_QUERY );
491 lcl_getChildCIDs( aSeriesSubContainer, xSeriesShapeContainer );
494 if( ! aSeriesSubContainer.empty())
495 m_aChildMap[ aSeriesCID ] = aSeriesSubContainer;
500 catch( uno::Exception & ex )
502 ASSERT_EXCEPTION( ex );
506 bool ImplObjectHierarchy::hasChildren( const OUString & rParent )
508 if( rParent.getLength())
510 tChildMap::const_iterator aIt( m_aChildMap.find( rParent ));
511 if( aIt != m_aChildMap.end())
512 return ! (aIt->second.empty());
514 return false;
517 ObjectHierarchy::tChildContainer ImplObjectHierarchy::getChildren( const OUString & rParent )
519 if( rParent.getLength())
521 tChildMap::const_iterator aIt( m_aChildMap.find( rParent ));
522 if( aIt != m_aChildMap.end())
523 return aIt->second;
525 return ObjectHierarchy::tChildContainer();
528 ObjectHierarchy::tChildContainer ImplObjectHierarchy::getSiblings( const OUString & rNode )
530 if( rNode.getLength() && !ObjectHierarchy::isRootNode( rNode ))
532 for( tChildMap::const_iterator aIt( m_aChildMap.begin());
533 aIt != m_aChildMap.end(); ++aIt )
535 ObjectHierarchy::tChildContainer::const_iterator aElemIt(
536 ::std::find( aIt->second.begin(), aIt->second.end(), rNode ));
537 if( aElemIt != aIt->second.end())
538 return aIt->second;
541 return ObjectHierarchy::tChildContainer();
544 ObjectHierarchy::tCID ImplObjectHierarchy::getParentImpl(
545 const ObjectHierarchy::tCID & rParentCID,
546 const ObjectHierarchy::tCID & rCID )
548 // search children
549 ObjectHierarchy::tChildContainer aChildren( getChildren( rParentCID ));
550 ObjectHierarchy::tChildContainer::const_iterator aIt(
551 ::std::find( aChildren.begin(), aChildren.end(), rCID ));
552 // recursion end
553 if( aIt != aChildren.end())
554 return rParentCID;
556 for( aIt = aChildren.begin(); aIt != aChildren.end(); ++aIt )
558 // recursion
559 ObjectHierarchy::tCID aTempParent( getParentImpl( *aIt, rCID ));
560 if( aTempParent.getLength())
562 // exit on success
563 return aTempParent;
567 // exit on fail
568 return ObjectHierarchy::tCID();
571 ObjectHierarchy::tCID ImplObjectHierarchy::getParent(
572 const ObjectHierarchy::tCID & rCID )
574 return getParentImpl( ObjectHierarchy::getRootNodeCID(), rCID );
577 } // namespace impl
579 ObjectHierarchy::ObjectHierarchy(
580 const Reference< XChartDocument > & xChartDocument,
581 ExplicitValueProvider * pExplicitValueProvider /* = 0 */,
582 bool bFlattenDiagram /* = false */,
583 bool bOrderingForElementSelector /* = false */) :
584 m_apImpl( new impl::ImplObjectHierarchy( xChartDocument, pExplicitValueProvider, bFlattenDiagram, bOrderingForElementSelector ))
587 ObjectHierarchy::~ObjectHierarchy()
590 // static
591 ObjectHierarchy::tCID ObjectHierarchy::getRootNodeCID()
593 return C2U("ROOT");
596 // static
597 bool ObjectHierarchy::isRootNode( const ObjectHierarchy::tCID & rCID )
599 return rCID.equals( ObjectHierarchy::getRootNodeCID());
602 ObjectHierarchy::tChildContainer ObjectHierarchy::getTopLevelChildren() const
604 return m_apImpl->getChildren( ObjectHierarchy::getRootNodeCID());
607 bool ObjectHierarchy::hasChildren( const tCID & rParent ) const
609 return m_apImpl->hasChildren( rParent );
612 ObjectHierarchy::tChildContainer ObjectHierarchy::getChildren(
613 const ObjectHierarchy::tCID & rParent ) const
615 if( rParent.getLength())
616 return m_apImpl->getChildren( rParent );
618 return ObjectHierarchy::tChildContainer();
621 ObjectHierarchy::tChildContainer ObjectHierarchy::getSiblings(
622 const ObjectHierarchy::tCID & rNode ) const
624 if( rNode.getLength() && !isRootNode( rNode ))
625 return m_apImpl->getSiblings( rNode );
627 return ObjectHierarchy::tChildContainer();
630 ObjectHierarchy::tCID ObjectHierarchy::getParent(
631 const ObjectHierarchy::tCID & rNode ) const
633 return m_apImpl->getParent( rNode );
636 sal_Int32 ObjectHierarchy::getIndexInParent(
637 const ObjectHierarchy::tCID & rNode ) const
639 tCID aParentCID( m_apImpl->getParent( rNode ));
640 tChildContainer aChildren( m_apImpl->getChildren( aParentCID ));
641 tChildContainer::const_iterator aIt( aChildren.begin());
642 for( sal_Int32 nIndex = 0; aIt != aChildren.end(); ++nIndex, ++aIt )
644 if( aIt->equals( rNode ))
645 return nIndex;
647 return -1;
650 // ================================================================================
652 ObjectKeyNavigation::ObjectKeyNavigation(
653 const ObjectHierarchy::tCID & rCurrentCID,
654 const Reference< chart2::XChartDocument > & xChartDocument,
655 ExplicitValueProvider * pExplicitValueProvider /* = 0 */ ) :
656 m_aCurrentCID( rCurrentCID ),
657 m_xChartDocument( xChartDocument ),
658 m_pExplicitValueProvider( pExplicitValueProvider ),
659 m_bStepDownInDiagram( true )
661 if( m_aCurrentCID.getLength() == 0 )
662 setCurrentSelection( ObjectHierarchy::getRootNodeCID());
665 bool ObjectKeyNavigation::handleKeyEvent(
666 const awt::KeyEvent & rEvent )
668 bool bResult = false;
670 switch( rEvent.KeyCode )
672 case awt::Key::TAB:
673 if( rEvent.Modifiers & awt::KeyModifier::SHIFT )
674 bResult = previous();
675 else
676 bResult = next();
677 break;
678 case awt::Key::HOME:
679 bResult = first();
680 break;
681 case awt::Key::END:
682 bResult = last();
683 break;
684 case awt::Key::F3:
685 if( rEvent.Modifiers & awt::KeyModifier::SHIFT )
686 bResult = up();
687 else
688 bResult = down();
689 break;
690 case awt::Key::ESCAPE:
691 setCurrentSelection( OUString());
692 bResult = true;
693 break;
694 default:
695 bResult = false;
696 break;
698 return bResult;
701 void ObjectKeyNavigation::setCurrentSelection( const ObjectHierarchy::tCID & rCID )
703 m_aCurrentCID = rCID;
706 ObjectHierarchy::tCID ObjectKeyNavigation::getCurrentSelection() const
708 return m_aCurrentCID;
711 bool ObjectKeyNavigation::first()
713 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
714 ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection()));
715 bool bResult = !aSiblings.empty();
716 if( bResult )
717 setCurrentSelection( aSiblings.front());
718 else
719 bResult = veryFirst();
720 return bResult;
723 bool ObjectKeyNavigation::last()
725 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
726 ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection()));
727 bool bResult = !aSiblings.empty();
728 if( bResult )
729 setCurrentSelection( aSiblings.back());
730 else
731 bResult = veryLast();
732 return bResult;
735 bool ObjectKeyNavigation::next()
737 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
738 ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection()));
739 bool bResult = !aSiblings.empty();
740 if( bResult )
742 ObjectHierarchy::tChildContainer::const_iterator aIt(
743 ::std::find( aSiblings.begin(), aSiblings.end(), getCurrentSelection()));
744 OSL_ASSERT( aIt != aSiblings.end());
745 if( ++aIt == aSiblings.end())
746 aIt = aSiblings.begin();
747 setCurrentSelection( *aIt );
749 else
750 bResult = veryFirst();
752 return bResult;
755 bool ObjectKeyNavigation::previous()
757 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
758 ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection()));
759 bool bResult = !aSiblings.empty();
760 if( bResult )
762 ObjectHierarchy::tChildContainer::const_iterator aIt(
763 ::std::find( aSiblings.begin(), aSiblings.end(), getCurrentSelection()));
764 OSL_ASSERT( aIt != aSiblings.end());
765 if( aIt == aSiblings.begin())
766 aIt = aSiblings.end();
767 --aIt;
768 setCurrentSelection( *aIt );
770 else
771 bResult = veryLast();
772 return bResult;
775 bool ObjectKeyNavigation::up()
777 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
778 bool bResult = !ObjectHierarchy::isRootNode( getCurrentSelection());
779 if( bResult )
780 setCurrentSelection( aHierarchy.getParent( getCurrentSelection()));
781 return bResult;
784 bool ObjectKeyNavigation::down()
786 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
787 bool bResult = aHierarchy.hasChildren( getCurrentSelection());
788 if( bResult )
790 ObjectHierarchy::tChildContainer aChildren = aHierarchy.getChildren( getCurrentSelection());
791 OSL_ASSERT( !aChildren.empty());
792 setCurrentSelection( aChildren.front());
794 return bResult;
797 bool ObjectKeyNavigation::veryFirst()
799 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
800 ObjectHierarchy::tChildContainer aChildren( aHierarchy.getTopLevelChildren());
801 bool bResult = !aChildren.empty();
802 if( bResult )
803 setCurrentSelection( aChildren.front());
804 return bResult;
807 bool ObjectKeyNavigation::veryLast()
809 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram );
810 ObjectHierarchy::tChildContainer aChildren( aHierarchy.getTopLevelChildren());
811 bool bResult = !aChildren.empty();
812 if( bResult )
813 setCurrentSelection( aChildren.back());
814 return bResult;
817 } // namespace chart