tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / chart2 / source / controller / main / ObjectHierarchy.cxx
blobe5603394b5af231d26dd72182a801a485ab83050
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 <Diagram.hxx>
23 #include <RegressionCurveHelper.hxx>
24 #include <RegressionCurveModel.hxx>
25 #include <Axis.hxx>
26 #include <AxisHelper.hxx>
27 #include <chartview/ExplicitValueProvider.hxx>
28 #include <ChartType.hxx>
29 #include <ChartTypeHelper.hxx>
30 #include <ChartModel.hxx>
31 #include <DataSeries.hxx>
32 #include <DataSeriesHelper.hxx>
33 #include <GridProperties.hxx>
34 #include <LegendHelper.hxx>
35 #include <chartview/DrawModelWrapper.hxx>
36 #include <unonames.hxx>
37 #include <BaseCoordinateSystem.hxx>
39 #include <map>
40 #include <algorithm>
41 #include <cstddef>
43 #include <com/sun/star/drawing/XShapes.hpp>
44 #include <com/sun/star/chart/ErrorBarStyle.hpp>
46 #include <com/sun/star/container/XIndexAccess.hpp>
47 #include <com/sun/star/awt/Key.hpp>
48 #include <com/sun/star/awt/KeyModifier.hpp>
49 #include <utility>
50 #include <comphelper/diagnose_ex.hxx>
52 using namespace ::com::sun::star;
53 using namespace ::com::sun::star::chart2;
55 using ::com::sun::star::uno::Reference;
57 namespace
60 void lcl_getChildOIDs(
61 ::chart::ObjectHierarchy::tChildContainer& rOutChildren,
62 const Reference< container::XIndexAccess >& xShapes )
64 if( !xShapes.is())
65 return;
67 sal_Int32 nCount = xShapes->getCount();
68 for( sal_Int32 i=0; i<nCount; ++i)
70 Reference< beans::XPropertySet > xShapeProp( xShapes->getByIndex( i ), uno::UNO_QUERY );
71 if( xShapeProp.is())
73 Reference< beans::XPropertySetInfo > xInfo( xShapeProp->getPropertySetInfo());
74 OUString aName;
75 if( xInfo.is() &&
76 xInfo->hasPropertyByName( u"Name"_ustr) &&
77 (xShapeProp->getPropertyValue( u"Name"_ustr) >>= aName ) &&
78 !aName.isEmpty() &&
79 ::chart::ObjectIdentifier::isCID( aName ))
81 rOutChildren.emplace_back( aName );
83 Reference< container::XIndexAccess > xNewShapes( xShapeProp, uno::UNO_QUERY );
84 if( xNewShapes.is())
85 lcl_getChildOIDs( rOutChildren, xNewShapes );
90 void lcl_addAxisTitle( const rtl::Reference< ::chart::Axis >& xAxis, ::chart::ObjectHierarchy::tChildContainer& rContainer, const rtl::Reference<::chart::ChartModel>& xChartModel )
92 if( xAxis.is())
94 Reference< XTitle > xAxisTitle( xAxis->getTitleObject());
95 if( xAxisTitle.is())
96 rContainer.emplace_back( ::chart::ObjectIdentifier::createClassifiedIdentifierForObject( xAxisTitle, xChartModel ) );
100 } // anonymous namespace
102 namespace chart
105 void ObjectHierarchy::createTree( const rtl::Reference<::chart::ChartModel>& xChartDocument )
107 m_aChildMap.clear();
109 if( !xChartDocument.is() )
110 return;
112 //@todo: change ObjectIdentifier to take an XChartDocument rather than XModel
113 rtl::Reference< Diagram > xDiagram = xChartDocument->getFirstChartDiagram();
114 ObjectIdentifier aDiaOID;
115 if( xDiagram.is() )
116 aDiaOID = ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( static_cast<cppu::OWeakObject*>(xDiagram.get()), xChartDocument ) );
117 tChildContainer aTopLevelContainer;
119 // First Level
121 // Chart Area
122 if( m_bOrderingForElementSelector )
124 aTopLevelContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, u"" ) );
125 if( xDiagram.is() )
127 aTopLevelContainer.push_back( aDiaOID );
128 createWallAndFloor( aTopLevelContainer, xDiagram );
129 createLegendTree( aTopLevelContainer, xChartDocument, xDiagram );
133 // Main Title
134 Reference< XTitle > xMainTitle( xChartDocument->getTitleObject());
135 if( xMainTitle.is())
136 aTopLevelContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifierForObject( xMainTitle, xChartDocument ) );
138 if( xDiagram.is())
140 // Sub Title. Note: This is interpreted of being top level
141 Reference< XTitle > xSubTitle( xDiagram->getTitleObject());
142 if( xSubTitle.is())
143 aTopLevelContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifierForObject( xSubTitle, xChartDocument ) );
145 if( !m_bOrderingForElementSelector )
147 // Axis Titles. Note: These are interpreted of being top level
148 const std::vector< rtl::Reference< Axis > > aAxes = AxisHelper::getAllAxesOfDiagram( xDiagram );
149 for( rtl::Reference< Axis > const & axis : aAxes )
150 lcl_addAxisTitle( axis, aTopLevelContainer, xChartDocument );
152 // Diagram
153 aTopLevelContainer.push_back( aDiaOID );
156 if( m_bFlattenDiagram )
157 createDiagramTree( aTopLevelContainer, xChartDocument, xDiagram );
158 else
160 tChildContainer aSubContainer;
161 createDiagramTree( aSubContainer, xChartDocument, xDiagram );
162 if( !aSubContainer.empty() )
163 m_aChildMap[ aDiaOID ] = std::move(aSubContainer);
166 if( !m_bOrderingForElementSelector )
167 createLegendTree( aTopLevelContainer, xChartDocument, xDiagram );
170 // #i12587# support for shapes in chart
171 if ( !m_bOrderingForElementSelector )
173 createAdditionalShapesTree( aTopLevelContainer );
176 // Chart Area
177 if( !m_bOrderingForElementSelector )
178 aTopLevelContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, u"" ) );
180 if( ! aTopLevelContainer.empty())
181 m_aChildMap[ObjectHierarchy::getRootNodeOID()] = std::move(aTopLevelContainer);
184 void ObjectHierarchy::createLegendTree(
185 tChildContainer & rContainer,
186 const rtl::Reference<::chart::ChartModel> & xChartDoc,
187 const rtl::Reference< Diagram > & xDiagram )
189 if( !(xDiagram.is() && LegendHelper::hasLegend( xDiagram )) )
190 return;
192 ObjectIdentifier aLegendOID( ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( xDiagram->getLegend(), xChartDoc ) ) );
193 rContainer.push_back( aLegendOID );
195 // iterate over child shapes of legend and search for matching CIDs
196 if( m_pExplicitValueProvider )
198 rtl::Reference< SvxShapeGroupAnyD > xLegendShapeContainer =
199 dynamic_cast<SvxShapeGroupAnyD*>(
200 m_pExplicitValueProvider->getShapeForCID( aLegendOID.getObjectCID() ).get() );
201 tChildContainer aLegendEntryOIDs;
202 lcl_getChildOIDs( aLegendEntryOIDs, xLegendShapeContainer );
204 m_aChildMap[aLegendOID] = std::move(aLegendEntryOIDs);
208 void ObjectHierarchy::createAxesTree(
209 tChildContainer & rContainer,
210 const rtl::Reference<::chart::ChartModel> & xChartDoc,
211 const rtl::Reference< Diagram > & xDiagram )
213 sal_Int32 nDimensionCount = xDiagram->getDimension();
214 rtl::Reference< ChartType > xChartType( xDiagram->getChartTypeByIndex( 0 ) );
215 bool bSupportsAxesGrids = ChartTypeHelper::isSupportingMainAxis( xChartType, nDimensionCount, 0 );
216 if( !bSupportsAxesGrids )
217 return;
219 // Data Table
220 uno::Reference<chart2::XDataTable> xDataTable = xDiagram->getDataTable();
221 if (xDataTable.is())
223 rContainer.push_back(ObjectIdentifier::createClassifiedIdentifierForObject(xDataTable, xChartDoc));
226 // Axes
227 std::vector< rtl::Reference< Axis > > aAxes = AxisHelper::getAllAxesOfDiagram( xDiagram, /* bOnlyVisible = */ true );
228 if( !m_bOrderingForElementSelector )
230 for (const auto& rAxis : aAxes)
231 rContainer.push_back( ObjectIdentifier::createClassifiedIdentifierForObject( rAxis, xChartDoc ) );
234 // get all axes, also invisible ones
235 aAxes = AxisHelper::getAllAxesOfDiagram( xDiagram );
236 // Grids
237 for( rtl::Reference< Axis > const & xAxis : aAxes )
239 if(!xAxis.is())
240 continue;
242 sal_Int32 nCooSysIndex = 0;
243 sal_Int32 nDimensionIndex = 0;
244 sal_Int32 nAxisIndex = 0;
245 AxisHelper::getIndicesForAxis( xAxis, xDiagram, nCooSysIndex, nDimensionIndex, nAxisIndex );
246 if( nAxisIndex>0 && !ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimensionCount ) )
247 continue;
249 if( m_bOrderingForElementSelector )
251 // axis
252 if( AxisHelper::isAxisVisible( xAxis ) )
253 rContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifierForObject( xAxis, xChartDoc ) );
255 // axis title
256 lcl_addAxisTitle( xAxis, rContainer, xChartDoc );
259 rtl::Reference< ::chart::GridProperties > xGridProperties( xAxis->getGridProperties2() );
260 if( AxisHelper::isGridVisible( xGridProperties ) )
262 //main grid
263 rContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifierForGrid( xAxis, xChartDoc ) );
266 std::vector< rtl::Reference< ::chart::GridProperties > > aSubGrids( xAxis->getSubGridProperties2() );
267 for( size_t nSubGrid = 0; nSubGrid < aSubGrids.size(); ++nSubGrid )
269 if( AxisHelper::isGridVisible( aSubGrids[nSubGrid] ) )
271 //sub grid
272 rContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifierForGrid( xAxis, xChartDoc, nSubGrid ) );
278 void ObjectHierarchy::createWallAndFloor(
279 tChildContainer & rContainer,
280 const rtl::Reference< Diagram > & xDiagram )
282 sal_Int32 nDimensionCount = xDiagram->getDimension();
283 bool bIsThreeD = ( nDimensionCount == 3 );
284 bool bHasWall = xDiagram->isSupportingFloorAndWall();
285 if( bHasWall && bIsThreeD )
287 rContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, u"" ) );
289 Reference< beans::XPropertySet > xFloor( xDiagram->getFloor());
290 if( xFloor.is())
291 rContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_FLOOR, u"" ) );
296 void ObjectHierarchy::createDiagramTree(
297 tChildContainer & rContainer,
298 const rtl::Reference<::chart::ChartModel> & xChartDoc,
299 const rtl::Reference< Diagram > & xDiagram )
301 if( !m_bOrderingForElementSelector )
303 createDataSeriesTree( rContainer, xDiagram );
304 createAxesTree( rContainer, xChartDoc, xDiagram );
305 createWallAndFloor( rContainer, xDiagram );
307 else
309 createAxesTree( rContainer, xChartDoc, xDiagram );
310 createDataSeriesTree( rContainer, xDiagram );
314 void ObjectHierarchy::createDataSeriesTree(
315 tChildContainer & rOutDiagramSubContainer,
316 const rtl::Reference< Diagram > & xDiagram )
320 sal_Int32 nDimensionCount = xDiagram->getDimension();
321 std::vector< rtl::Reference< BaseCoordinateSystem > > aCooSysSeq(
322 xDiagram->getBaseCoordinateSystems());
323 for( std::size_t nCooSysIdx=0; nCooSysIdx<aCooSysSeq.size(); ++nCooSysIdx )
325 std::vector< rtl::Reference< ChartType > > aChartTypeSeq( aCooSysSeq[nCooSysIdx]->getChartTypes2());
326 for( std::size_t nCTIdx=0; nCTIdx<aChartTypeSeq.size(); ++nCTIdx )
328 const rtl::Reference< ChartType >& xChartType( aChartTypeSeq[nCTIdx] );
329 std::vector< rtl::Reference< DataSeries > > aSeriesSeq( xChartType->getDataSeries2() );
330 const sal_Int32 nNumberOfSeries =
331 ChartTypeHelper::getNumberOfDisplayedSeries( xChartType, aSeriesSeq.size());
333 for( sal_Int32 nSeriesIdx=0; nSeriesIdx<nNumberOfSeries; ++nSeriesIdx )
335 OUString aSeriesParticle(
336 ObjectIdentifier::createParticleForSeries(
337 0, nCooSysIdx, nCTIdx, nSeriesIdx ));
338 ObjectIdentifier aSeriesOID(
339 ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForParticle( aSeriesParticle ) ) );
340 rOutDiagramSubContainer.push_back( aSeriesOID );
342 tChildContainer aSeriesSubContainer;
344 rtl::Reference< DataSeries > const & xSeries = aSeriesSeq[nSeriesIdx];
346 // data labels
347 if( DataSeriesHelper::hasDataLabelsAtSeries( xSeries ) )
349 OUString aChildParticle( ObjectIdentifier::getStringForType( OBJECTTYPE_DATA_LABELS ) + "=" );
350 aSeriesSubContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifierForParticles( aSeriesParticle, aChildParticle ) );
353 // Statistics
354 if( ChartTypeHelper::isSupportingStatisticProperties( xChartType, nDimensionCount ) )
356 const std::vector< rtl::Reference< RegressionCurveModel > > & rCurves( xSeries->getRegressionCurves2());
357 for( size_t nCurveIdx=0; nCurveIdx<rCurves.size(); ++nCurveIdx )
359 bool bIsAverageLine = RegressionCurveHelper::isMeanValueLine( rCurves[nCurveIdx] );
360 aSeriesSubContainer.emplace_back( ObjectIdentifier::createDataCurveCID( aSeriesParticle, nCurveIdx, bIsAverageLine ) );
361 if( RegressionCurveHelper::hasEquation( rCurves[nCurveIdx] ) )
363 aSeriesSubContainer.emplace_back( ObjectIdentifier::createDataCurveEquationCID( aSeriesParticle, nCurveIdx ) );
366 Reference< beans::XPropertySet > xErrorBarProp;
367 if( (xSeries->getPropertyValue( CHART_UNONAME_ERRORBAR_Y) >>= xErrorBarProp) &&
368 xErrorBarProp.is())
370 sal_Int32 nStyle = css::chart::ErrorBarStyle::NONE;
371 if( ( xErrorBarProp->getPropertyValue( u"ErrorBarStyle"_ustr) >>= nStyle ) &&
372 ( nStyle != css::chart::ErrorBarStyle::NONE ) )
374 aSeriesSubContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifierWithParent(
375 OBJECTTYPE_DATA_ERRORS_Y, u"", aSeriesParticle ) );
379 if( (xSeries->getPropertyValue(CHART_UNONAME_ERRORBAR_X) >>= xErrorBarProp) &&
380 xErrorBarProp.is())
382 sal_Int32 nStyle = css::chart::ErrorBarStyle::NONE;
383 if( ( xErrorBarProp->getPropertyValue( u"ErrorBarStyle"_ustr) >>= nStyle ) &&
384 ( nStyle != css::chart::ErrorBarStyle::NONE ) )
386 aSeriesSubContainer.emplace_back( ObjectIdentifier::createClassifiedIdentifierWithParent(
387 OBJECTTYPE_DATA_ERRORS_X, u"", aSeriesParticle ) );
392 // Data Points
393 // iterate over child shapes of legend and search for matching CIDs
394 if( m_pExplicitValueProvider )
396 rtl::Reference< SvxShapeGroupAnyD > xSeriesShapeContainer =
397 dynamic_cast<SvxShapeGroupAnyD*>(
398 m_pExplicitValueProvider->getShapeForCID( aSeriesOID.getObjectCID() ).get() );
399 lcl_getChildOIDs( aSeriesSubContainer, xSeriesShapeContainer );
402 if( ! aSeriesSubContainer.empty())
403 m_aChildMap[ aSeriesOID ] = std::move(aSeriesSubContainer);
408 catch( const uno::Exception & )
410 DBG_UNHANDLED_EXCEPTION("chart2");
414 void ObjectHierarchy::createAdditionalShapesTree(tChildContainer& rContainer)
418 if ( m_pExplicitValueProvider )
420 rtl::Reference<SvxDrawPage> xDrawPage( m_pExplicitValueProvider->getDrawModelWrapper()->getMainDrawPage() );
421 Reference< drawing::XShapes > xChartRoot( DrawModelWrapper::getChartRootShape( xDrawPage ) );
422 sal_Int32 nCount = xDrawPage->getCount();
423 for ( sal_Int32 i = 0; i < nCount; ++i )
425 Reference< drawing::XShape > xShape;
426 if ( xDrawPage->getByIndex( i ) >>= xShape )
428 if ( xShape.is() && xShape != xChartRoot )
430 rContainer.emplace_back( xShape );
436 catch ( const uno::Exception& )
438 DBG_UNHANDLED_EXCEPTION("chart2");
442 bool ObjectHierarchy::hasChildren( const ObjectIdentifier& rParent ) const
444 if ( rParent.isValid() )
446 tChildMap::const_iterator aIt( m_aChildMap.find( rParent ));
447 if( aIt != m_aChildMap.end())
448 return ! (aIt->second.empty());
450 return false;
453 const ObjectHierarchy::tChildContainer & ObjectHierarchy::getChildren( const ObjectIdentifier& rParent ) const
455 if ( rParent.isValid() )
457 tChildMap::const_iterator aIt( m_aChildMap.find( rParent ));
458 if( aIt != m_aChildMap.end())
459 return aIt->second;
461 static const tChildContainer EMPTY;
462 return EMPTY;
465 const ObjectHierarchy::tChildContainer & ObjectHierarchy::getSiblings( const ObjectIdentifier& rNode ) const
467 if ( rNode.isValid() && !ObjectHierarchy::isRootNode( rNode ) )
469 for (auto const& child : m_aChildMap)
471 tChildContainer::const_iterator aElemIt(
472 std::find( child.second.begin(), child.second.end(), rNode ));
473 if( aElemIt != child.second.end())
474 return child.second;
477 static const tChildContainer EMPTY;
478 return EMPTY;
481 ObjectIdentifier ObjectHierarchy::getParentImpl(
482 const ObjectIdentifier & rParentOID,
483 const ObjectIdentifier & rOID ) const
485 // search children
486 tChildContainer aChildren( getChildren( rParentOID ));
487 tChildContainer::const_iterator aIt(
488 std::find( aChildren.begin(), aChildren.end(), rOID ));
489 // recursion end
490 if( aIt != aChildren.end())
491 return rParentOID;
493 for (auto const& child : aChildren)
495 // recursion
496 ObjectIdentifier aTempParent( getParentImpl( child, rOID ));
497 if ( aTempParent.isValid() )
499 // exit on success
500 return aTempParent;
504 // exit on fail
505 return ObjectIdentifier();
508 ObjectIdentifier ObjectHierarchy::getParent(
509 const ObjectIdentifier & rOID ) const
511 return getParentImpl( ObjectHierarchy::getRootNodeOID(), rOID );
514 ObjectHierarchy::ObjectHierarchy(
515 const rtl::Reference<::chart::ChartModel> & xChartDocument,
516 ExplicitValueProvider * pExplicitValueProvider /* = 0 */,
517 bool bFlattenDiagram /* = false */,
518 bool bOrderingForElementSelector /* = false */) :
519 m_pExplicitValueProvider( pExplicitValueProvider ),
520 m_bFlattenDiagram( bFlattenDiagram ),
521 m_bOrderingForElementSelector( bOrderingForElementSelector )
523 createTree( xChartDocument );
524 // don't remember this helper to avoid access after lifetime
525 m_pExplicitValueProvider = nullptr;
528 ObjectHierarchy::~ObjectHierarchy()
531 ObjectIdentifier ObjectHierarchy::getRootNodeOID()
533 return ObjectIdentifier( u"ROOT"_ustr );
536 bool ObjectHierarchy::isRootNode( const ObjectIdentifier& rOID )
538 return ( rOID == ObjectHierarchy::getRootNodeOID() );
541 const ObjectHierarchy::tChildContainer & ObjectHierarchy::getTopLevelChildren() const
543 return getChildren( ObjectHierarchy::getRootNodeOID());
546 sal_Int32 ObjectHierarchy::getIndexInParent(
547 const ObjectIdentifier& rNode ) const
549 ObjectIdentifier aParentOID( getParent( rNode ));
550 const tChildContainer & aChildren( getChildren( aParentOID ) );
551 sal_Int32 nIndex = 0;
552 for (auto const& child : aChildren)
554 if ( child == rNode )
555 return nIndex;
556 ++nIndex;
558 return -1;
561 ObjectKeyNavigation::ObjectKeyNavigation(
562 ObjectIdentifier aCurrentOID,
563 rtl::Reference<::chart::ChartModel> xChartDocument,
564 ExplicitValueProvider * pExplicitValueProvider /* = 0 */ ) :
565 m_aCurrentOID(std::move( aCurrentOID )),
566 m_xChartDocument(std::move( xChartDocument )),
567 m_pExplicitValueProvider( pExplicitValueProvider )
569 if ( !m_aCurrentOID.isValid() )
571 setCurrentSelection( ObjectHierarchy::getRootNodeOID() );
575 bool ObjectKeyNavigation::handleKeyEvent(
576 const awt::KeyEvent & rEvent )
578 bool bResult = false;
580 switch( rEvent.KeyCode )
582 case awt::Key::TAB:
583 if( rEvent.Modifiers & awt::KeyModifier::SHIFT )
584 bResult = previous();
585 else
586 bResult = next();
587 break;
588 case awt::Key::HOME:
589 bResult = first();
590 break;
591 case awt::Key::END:
592 bResult = last();
593 break;
594 case awt::Key::F3:
595 if( rEvent.Modifiers & awt::KeyModifier::SHIFT )
596 bResult = up();
597 else
598 bResult = down();
599 break;
600 case awt::Key::ESCAPE:
601 setCurrentSelection( ObjectIdentifier() );
602 bResult = true;
603 break;
604 default:
605 bResult = false;
606 break;
608 return bResult;
611 void ObjectKeyNavigation::setCurrentSelection( const ObjectIdentifier& rOID )
613 m_aCurrentOID = rOID;
616 bool ObjectKeyNavigation::first()
618 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider );
619 const ObjectHierarchy::tChildContainer& aSiblings( aHierarchy.getSiblings( getCurrentSelection() ) );
620 bool bResult = !aSiblings.empty();
621 if( bResult )
622 setCurrentSelection( aSiblings.front());
623 else
624 bResult = veryFirst();
625 return bResult;
628 bool ObjectKeyNavigation::last()
630 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider );
631 const ObjectHierarchy::tChildContainer& aSiblings( aHierarchy.getSiblings( getCurrentSelection() ) );
632 bool bResult = !aSiblings.empty();
633 if( bResult )
634 setCurrentSelection( aSiblings.back());
635 else
636 bResult = veryLast();
637 return bResult;
640 bool ObjectKeyNavigation::next()
642 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider );
643 ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection() ) );
644 bool bResult = !aSiblings.empty();
645 if( bResult )
647 ObjectHierarchy::tChildContainer::const_iterator aIt(
648 std::find( aSiblings.begin(), aSiblings.end(), getCurrentSelection()));
649 assert(aIt != aSiblings.end());
650 if( ++aIt == aSiblings.end())
651 aIt = aSiblings.begin();
652 setCurrentSelection( *aIt );
654 else
655 bResult = veryFirst();
657 return bResult;
660 bool ObjectKeyNavigation::previous()
662 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider );
663 ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection()));
664 bool bResult = !aSiblings.empty();
665 if( bResult )
667 ObjectHierarchy::tChildContainer::const_iterator aIt(
668 std::find( aSiblings.begin(), aSiblings.end(), getCurrentSelection()));
669 OSL_ASSERT( aIt != aSiblings.end());
670 if( aIt == aSiblings.begin())
671 aIt = aSiblings.end();
672 --aIt;
673 setCurrentSelection( *aIt );
675 else
676 bResult = veryLast();
677 return bResult;
680 bool ObjectKeyNavigation::up()
682 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider );
683 bool bResult = !ObjectHierarchy::isRootNode( getCurrentSelection());
684 if( bResult )
685 setCurrentSelection( aHierarchy.getParent( getCurrentSelection()));
686 return bResult;
689 bool ObjectKeyNavigation::down()
691 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider );
692 bool bResult = aHierarchy.hasChildren( getCurrentSelection());
693 if( bResult )
695 const ObjectHierarchy::tChildContainer& aChildren = aHierarchy.getChildren( getCurrentSelection());
696 OSL_ASSERT( !aChildren.empty());
697 setCurrentSelection( aChildren.front());
699 return bResult;
702 bool ObjectKeyNavigation::veryFirst()
704 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider );
705 const ObjectHierarchy::tChildContainer& aChildren( aHierarchy.getTopLevelChildren());
706 bool bResult = !aChildren.empty();
707 if( bResult )
708 setCurrentSelection( aChildren.front());
709 return bResult;
712 bool ObjectKeyNavigation::veryLast()
714 ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider );
715 const ObjectHierarchy::tChildContainer& aChildren( aHierarchy.getTopLevelChildren());
716 bool bResult = !aChildren.empty();
717 if( bResult )
718 setCurrentSelection( aChildren.back());
719 return bResult;
722 } // namespace chart
724 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */