/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2008 by Sun Microsystems, Inc. * * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: ObjectHierarchy.cxx,v $ * $Revision: 1.7 $ * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_chart2.hxx" #include "ObjectHierarchy.hxx" #include "ObjectIdentifier.hxx" #include "ChartModelHelper.hxx" #include "DiagramHelper.hxx" #include "RegressionCurveHelper.hxx" #include "AxisHelper.hxx" #include "chartview/ExplicitValueProvider.hxx" #include "macros.hxx" #include "LineProperties.hxx" #include "ChartTypeHelper.hxx" #include "chartview/DrawModelWrapper.hxx" #include #include #include #include #include #include #include #include #include #include using namespace ::com::sun::star; using namespace ::com::sun::star::chart2; using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::Sequence; using ::rtl::OUString; namespace { struct lcl_ObjectToOID : public ::std::unary_function< Reference< uno::XInterface >, ::chart::ObjectIdentifier > { explicit lcl_ObjectToOID( const Reference< chart2::XChartDocument > & xChartDoc ) : m_xModel( xChartDoc, uno::UNO_QUERY ) {} ::chart::ObjectIdentifier operator() ( const Reference< uno::XInterface > & xObj ) { return ::chart::ObjectIdentifier( ::chart::ObjectIdentifier::createClassifiedIdentifierForObject( xObj, m_xModel ) ); } private: Reference< frame::XModel > m_xModel; }; void lcl_getChildOIDs( ::chart::ObjectHierarchy::tChildContainer& rOutChildren, const Reference< container::XIndexAccess >& xShapes ) { if( xShapes.is()) { sal_Int32 nCount = xShapes->getCount(); for( sal_Int32 i=0; i xShapeProp( xShapes->getByIndex( i ), uno::UNO_QUERY ); if( xShapeProp.is()) { Reference< beans::XPropertySetInfo > xInfo( xShapeProp->getPropertySetInfo()); OUString aName; if( xInfo.is() && xInfo->hasPropertyByName( C2U("Name")) && (xShapeProp->getPropertyValue( C2U("Name")) >>= aName ) && aName.getLength() > 0 && ::chart::ObjectIdentifier::isCID( aName )) { rOutChildren.push_back( ::chart::ObjectIdentifier( aName ) ); } Reference< container::XIndexAccess > xNewShapes( xShapeProp, uno::UNO_QUERY ); if( xNewShapes.is()) lcl_getChildOIDs( rOutChildren, xNewShapes ); } } } } } // anonymous namespace namespace chart { namespace impl { class ImplObjectHierarchy { public: explicit ImplObjectHierarchy( const Reference< XChartDocument >& xChartDocument, ExplicitValueProvider* pExplicitValueProvider, bool bFlattenDiagram ); bool hasChildren( const ObjectHierarchy::tOID& rParent ); ObjectHierarchy::tChildContainer getChildren( const ObjectHierarchy::tOID& rParent ); ObjectHierarchy::tChildContainer getSiblings( const ObjectHierarchy::tOID& rNode ); ObjectHierarchy::tOID getParent( const ObjectHierarchy::tOID& rOID ); private: void createTree( const Reference< XChartDocument > & xChartDocument ); void createDiagramTree( ObjectHierarchy::tChildContainer& rContainer, const Reference< XChartDocument >& xChartDoc, const Reference< XDiagram >& xDiagram ); void createDataSeriesTree( ObjectHierarchy::tChildContainer& rOutDiagramSubContainer, const Reference< XCoordinateSystemContainer >& xCooSysCnt ); void createAdditionalShapesTree( ObjectHierarchy::tChildContainer& rContainer ); ObjectHierarchy::tOID getParentImpl( const ObjectHierarchy::tOID& rParentOID, const ObjectHierarchy::tOID& rOID ); typedef ::std::map< ObjectHierarchy::tOID, ObjectHierarchy::tChildContainer > tChildMap; tChildMap m_aChildMap; ExplicitValueProvider* m_pExplicitValueProvider; bool m_bFlattenDiagram; }; ImplObjectHierarchy::ImplObjectHierarchy( const Reference< XChartDocument >& xChartDocument, ExplicitValueProvider* pExplicitValueProvider, bool bFlattenDiagram ) : m_pExplicitValueProvider( pExplicitValueProvider ), m_bFlattenDiagram( bFlattenDiagram ) { createTree( xChartDocument ); // don't remember this helper to avoid access after lifetime m_pExplicitValueProvider = 0; } void ImplObjectHierarchy::createTree( const Reference< XChartDocument >& xChartDocument ) { if( !xChartDocument.is() ) return; //@todo: change ObjectIdentifier to take an XChartDocument rather than XModel Reference< frame::XModel > xModel( xChartDocument, uno::UNO_QUERY ); ObjectHierarchy::tChildContainer aTopLevelContainer; // First Level // Main Title Reference< XTitled > xDocTitled( xChartDocument, uno::UNO_QUERY ); if( xDocTitled.is()) { Reference< XTitle > xMainTitle( xDocTitled->getTitleObject()); if( xMainTitle.is()) aTopLevelContainer.push_back( ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( xMainTitle, xModel ) ) ); } Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartDocument )); if( xDiagram.is()) { // Sub Title. Note: This is interpreted of being top level Reference< XTitled > xDiaTitled( xDiagram, uno::UNO_QUERY ); if( xDiaTitled.is()) { Reference< XTitle > xSubTitle( xDiaTitled->getTitleObject()); if( xSubTitle.is()) aTopLevelContainer.push_back( ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( xSubTitle, xModel ) ) ); } // Axis Titles. Note: These are interpreted of being top level Sequence< Reference< XAxis > > aAxes( AxisHelper::getAllAxesOfDiagram( xDiagram ) ); for( sal_Int32 i=0; i xAxisTitled( aAxes[i], uno::UNO_QUERY ); if( xAxisTitled.is()) { Reference< XTitle > xAxisTitle( xAxisTitled->getTitleObject()); if( xAxisTitle.is()) aTopLevelContainer.push_back( ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( xAxisTitle, xModel ) ) ); } } // Diagram ObjectHierarchy::tOID aDiaOID( ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( xDiagram, xModel ) ) ); OSL_ASSERT( aDiaOID.getObjectCID().getLength() ); aTopLevelContainer.push_back( aDiaOID ); if( m_bFlattenDiagram ) createDiagramTree( aTopLevelContainer, xChartDocument, xDiagram ); else { ObjectHierarchy::tChildContainer aSubContainer; createDiagramTree( aSubContainer, xChartDocument, xDiagram ); if( !aSubContainer.empty() ) m_aChildMap[ aDiaOID ] = aSubContainer; } // Legend. Note: This is interpreted of being top level Reference< XLegend > xLegend( xDiagram->getLegend()); if( xLegend.is()) { Reference< beans::XPropertySet > xLegendProp( xLegend, uno::UNO_QUERY ); bool bShow = false; if( xLegendProp.is() && (xLegendProp->getPropertyValue( C2U("Show")) >>= bShow) && bShow ) { ObjectHierarchy::tOID aLegendOID( ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( xLegend, xModel ) ) ); aTopLevelContainer.push_back( aLegendOID ); // iterate over child shapes of legend and search for matching OIDs if( m_pExplicitValueProvider ) { Reference< container::XIndexAccess > xLegendShapeContainer( m_pExplicitValueProvider->getShapeForCID( aLegendOID.getObjectCID() ), uno::UNO_QUERY ); ObjectHierarchy::tChildContainer aLegendEntryOIDs; lcl_getChildOIDs( aLegendEntryOIDs, xLegendShapeContainer ); m_aChildMap[ aLegendOID ] = aLegendEntryOIDs; } } } } // #i12587# support for shapes in chart createAdditionalShapesTree( aTopLevelContainer ); // Chart Area aTopLevelContainer.push_back( ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, OUString() ) ) ); if( ! aTopLevelContainer.empty()) m_aChildMap[ ObjectHierarchy::getRootNodeOID() ] = aTopLevelContainer; } void ImplObjectHierarchy::createDiagramTree( ObjectHierarchy::tChildContainer& rContainer, const Reference< XChartDocument >& xChartDoc, const Reference< XDiagram >& xDiagram ) { // Data Series Reference< XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW ); createDataSeriesTree( rContainer, xCooSysCnt ); // Axes sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram ); uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ); bool bSupportsAxesGrids = ChartTypeHelper::isSupportingMainAxis( xChartType, nDimensionCount, 0 ); bool bIsThreeD = ( nDimensionCount == 3 ); bool bHasWall = DiagramHelper::isSupportingFloorAndWall( xDiagram ); if( bSupportsAxesGrids ) { Sequence< Reference< XAxis > > aAxes( AxisHelper::getAllAxesOfDiagram( xDiagram, /* bOnlyVisible = */ true ) ); ::std::transform( aAxes.getConstArray(), aAxes.getConstArray() + aAxes.getLength(), ::std::back_inserter( rContainer ), lcl_ObjectToOID( xChartDoc )); // get all axes, also invisible ones aAxes = AxisHelper::getAllAxesOfDiagram( xDiagram, /* bOnlyVisible = */ false ); // Grids Reference< frame::XModel > xChartModel( xChartDoc, uno::UNO_QUERY ); for( sal_Int32 nA=0; nA xAxis( aAxes[nA] ); if(!xAxis.is()) continue; Reference< beans::XPropertySet > xGridProperties( xAxis->getGridProperties() ); if( AxisHelper::isGridVisible( xGridProperties ) ) { //main grid rContainer.push_back( ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForGrid( xAxis, xChartModel ) ) ); } Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() );; sal_Int32 nSubGrid = 0; for( nSubGrid = 0; nSubGrid < aSubGrids.getLength(); ++nSubGrid ) { Reference< beans::XPropertySet > xSubGridProperties( aSubGrids[nSubGrid] ); if( AxisHelper::isGridVisible( xSubGridProperties ) ) { //sub grid rContainer.push_back( ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForGrid( xAxis, xChartModel, nSubGrid ) ) ); } } } } // Wall if( bHasWall ) { rContainer.push_back( ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, rtl::OUString() ) ) ); } // Floor if( bHasWall && bIsThreeD ) { Reference< beans::XPropertySet > xFloor( xDiagram->getFloor()); if( xFloor.is()) rContainer.push_back( ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_FLOOR, rtl::OUString() ) ) ); } } void ImplObjectHierarchy::createDataSeriesTree( ObjectHierarchy::tChildContainer& rOutDiagramSubContainer, const Reference< XCoordinateSystemContainer >& xCooSysCnt ) { try { sal_Int32 nDiagramIndex = 0; Sequence< Reference< XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems()); for( sal_Int32 nCooSysIdx=0; nCooSysIdx xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW ); Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes()); for( sal_Int32 nCTIdx=0; nCTIdx xDSCnt( aChartTypeSeq[nCTIdx], uno::UNO_QUERY_THROW ); Sequence< Reference< XDataSeries > > aSeriesSeq( xDSCnt->getDataSeries() ); const sal_Int32 nNumberOfSeries = ChartTypeHelper::getNumberOfDisplayedSeries( aChartTypeSeq[nCTIdx], aSeriesSeq.getLength()); for( sal_Int32 nSeriesIdx=0; nSeriesIdx xCurveCnt( aSeriesSeq[nSeriesIdx], uno::UNO_QUERY ); if( xCurveCnt.is()) { Sequence< Reference< chart2::XRegressionCurve > > aCurves( xCurveCnt->getRegressionCurves()); for( sal_Int32 nCurveIdx=0; nCurveIdx xEqProp( aCurves[nCurveIdx]->getEquationProperties()); bool bShowEq = false; bool bShowCoeff = false; if( xEqProp.is() && ( (xEqProp->getPropertyValue( C2U("ShowEquation")) >>= bShowEq) || (xEqProp->getPropertyValue( C2U("ShowCorrelationCoefficient")) >>= bShowCoeff) ) && ( bShowEq || bShowCoeff ) ) { aSeriesSubContainer.push_back( ObjectIdentifier( ObjectIdentifier::createDataCurveEquationCID( aSeriesParticle, nCurveIdx ) ) ); } } Reference< beans::XPropertySet > xSeriesProp( aSeriesSeq[nSeriesIdx], uno::UNO_QUERY ); Reference< beans::XPropertySet > xErrorBarProp; if( xSeriesProp.is() && (xSeriesProp->getPropertyValue( C2U("ErrorBarY")) >>= xErrorBarProp) && xErrorBarProp.is()) { sal_Int32 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE; if( ( xErrorBarProp->getPropertyValue( C2U("ErrorBarStyle")) >>= nStyle ) && ( nStyle != ::com::sun::star::chart::ErrorBarStyle::NONE ) ) { aSeriesSubContainer.push_back( ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierWithParent( OBJECTTYPE_DATA_ERRORS, OUString(), aSeriesParticle ) ) ); } } } // Data Points // iterate over child shapes of legend and search for matching CIDs if( m_pExplicitValueProvider ) { Reference< container::XIndexAccess > xSeriesShapeContainer( m_pExplicitValueProvider->getShapeForCID( aSeriesOID.getObjectCID() ), uno::UNO_QUERY ); lcl_getChildOIDs( aSeriesSubContainer, xSeriesShapeContainer ); } if( ! aSeriesSubContainer.empty()) m_aChildMap[ aSeriesOID ] = aSeriesSubContainer; } } } } catch( uno::Exception & ex ) { ASSERT_EXCEPTION( ex ); } } void ImplObjectHierarchy::createAdditionalShapesTree( ObjectHierarchy::tChildContainer& rContainer ) { try { if ( m_pExplicitValueProvider ) { Reference< drawing::XDrawPage > xDrawPage( m_pExplicitValueProvider->getDrawModelWrapper()->getMainDrawPage() ); Reference< drawing::XShapes > xDrawPageShapes( xDrawPage, uno::UNO_QUERY_THROW ); Reference< drawing::XShapes > xChartRoot( DrawModelWrapper::getChartRootShape( xDrawPage ) ); sal_Int32 nCount = xDrawPageShapes->getCount(); for ( sal_Int32 i = 0; i < nCount; ++i ) { Reference< drawing::XShape > xShape; if ( xDrawPageShapes->getByIndex( i ) >>= xShape ) { if ( xShape.is() && xShape != xChartRoot ) { rContainer.push_back( ObjectIdentifier( xShape ) ); } } } } } catch ( uno::Exception& ex ) { ASSERT_EXCEPTION( ex ); } } bool ImplObjectHierarchy::hasChildren( const ObjectHierarchy::tOID& rParent ) { if ( rParent.isValid() ) { tChildMap::const_iterator aIt( m_aChildMap.find( rParent )); if( aIt != m_aChildMap.end()) return ! (aIt->second.empty()); } return false; } ObjectHierarchy::tChildContainer ImplObjectHierarchy::getChildren( const ObjectHierarchy::tOID& rParent ) { if ( rParent.isValid() ) { tChildMap::const_iterator aIt( m_aChildMap.find( rParent )); if( aIt != m_aChildMap.end()) return aIt->second; } return ObjectHierarchy::tChildContainer(); } ObjectHierarchy::tChildContainer ImplObjectHierarchy::getSiblings( const ObjectHierarchy::tOID& rNode ) { if ( rNode.isValid() && !ObjectHierarchy::isRootNode( rNode ) ) { for( tChildMap::const_iterator aIt( m_aChildMap.begin()); aIt != m_aChildMap.end(); ++aIt ) { ObjectHierarchy::tChildContainer::const_iterator aElemIt( ::std::find( aIt->second.begin(), aIt->second.end(), rNode )); if( aElemIt != aIt->second.end()) return aIt->second; } } return ObjectHierarchy::tChildContainer(); } ObjectHierarchy::tOID ImplObjectHierarchy::getParentImpl( const ObjectHierarchy::tOID & rParentOID, const ObjectHierarchy::tOID & rOID ) { // search children ObjectHierarchy::tChildContainer aChildren( getChildren( rParentOID )); ObjectHierarchy::tChildContainer::const_iterator aIt( ::std::find( aChildren.begin(), aChildren.end(), rOID )); // recursion end if( aIt != aChildren.end()) return rParentOID; for( aIt = aChildren.begin(); aIt != aChildren.end(); ++aIt ) { // recursion ObjectHierarchy::tOID aTempParent( getParentImpl( *aIt, rOID )); if ( aTempParent.isValid() ) { // exit on success return aTempParent; } } // exit on fail return ObjectHierarchy::tOID(); } ObjectHierarchy::tOID ImplObjectHierarchy::getParent( const ObjectHierarchy::tOID & rOID ) { return getParentImpl( ObjectHierarchy::getRootNodeOID(), rOID ); } } // namespace impl ObjectHierarchy::ObjectHierarchy( const Reference< XChartDocument > & xChartDocument, ExplicitValueProvider * pExplicitValueProvider /* = 0 */, bool bFlattenDiagram /* = false */ ) : m_apImpl( new impl::ImplObjectHierarchy( xChartDocument, pExplicitValueProvider, bFlattenDiagram )) {} ObjectHierarchy::~ObjectHierarchy() {} // static ObjectHierarchy::tOID ObjectHierarchy::getRootNodeOID() { return ObjectIdentifier( C2U( "ROOT" ) ); } // static bool ObjectHierarchy::isRootNode( const ObjectHierarchy::tOID& rOID ) { return ( rOID == ObjectHierarchy::getRootNodeOID() ); } ObjectHierarchy::tChildContainer ObjectHierarchy::getTopLevelChildren() const { return m_apImpl->getChildren( ObjectHierarchy::getRootNodeOID()); } bool ObjectHierarchy::hasChildren( const tOID& rParent ) const { return m_apImpl->hasChildren( rParent ); } ObjectHierarchy::tChildContainer ObjectHierarchy::getChildren( const ObjectHierarchy::tOID& rParent ) const { if ( rParent.isValid() ) return m_apImpl->getChildren( rParent ); return ObjectHierarchy::tChildContainer(); } ObjectHierarchy::tChildContainer ObjectHierarchy::getSiblings( const ObjectHierarchy::tOID& rNode ) const { if ( rNode.isValid() && !isRootNode( rNode ) ) return m_apImpl->getSiblings( rNode ); return ObjectHierarchy::tChildContainer(); } ObjectHierarchy::tOID ObjectHierarchy::getParent( const ObjectHierarchy::tOID& rNode ) const { return m_apImpl->getParent( rNode ); } sal_Int32 ObjectHierarchy::getIndexInParent( const ObjectHierarchy::tOID& rNode ) const { tOID aParentOID( m_apImpl->getParent( rNode )); tChildContainer aChildren( m_apImpl->getChildren( aParentOID ) ); tChildContainer::const_iterator aIt( aChildren.begin() ); for( sal_Int32 nIndex = 0; aIt != aChildren.end(); ++nIndex, ++aIt ) { if ( *aIt == rNode ) return nIndex; } return -1; } // ================================================================================ ObjectKeyNavigation::ObjectKeyNavigation( const ObjectHierarchy::tOID & rCurrentOID, const Reference< chart2::XChartDocument > & xChartDocument, ExplicitValueProvider * pExplicitValueProvider /* = 0 */ ) : m_aCurrentOID( rCurrentOID ), m_xChartDocument( xChartDocument ), m_pExplicitValueProvider( pExplicitValueProvider ), m_bStepDownInDiagram( true ) { if ( !m_aCurrentOID.isValid() ) { setCurrentSelection( ObjectHierarchy::getRootNodeOID() ); } } bool ObjectKeyNavigation::handleKeyEvent( const awt::KeyEvent & rEvent ) { bool bResult = false; switch( rEvent.KeyCode ) { case awt::Key::TAB: if( rEvent.Modifiers & awt::KeyModifier::SHIFT ) bResult = previous(); else bResult = next(); break; case awt::Key::HOME: bResult = first(); break; case awt::Key::END: bResult = last(); break; case awt::Key::F3: if( rEvent.Modifiers & awt::KeyModifier::SHIFT ) bResult = up(); else bResult = down(); break; case awt::Key::ESCAPE: setCurrentSelection( ObjectIdentifier() ); bResult = true; break; default: bResult = false; break; } return bResult; } void ObjectKeyNavigation::setCurrentSelection( const ObjectHierarchy::tOID& rOID ) { m_aCurrentOID = rOID; } ObjectHierarchy::tOID ObjectKeyNavigation::getCurrentSelection() const { return m_aCurrentOID; } bool ObjectKeyNavigation::first() { ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram ); ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection() ) ); bool bResult = !aSiblings.empty(); if( bResult ) setCurrentSelection( aSiblings.front()); else bResult = veryFirst(); return bResult; } bool ObjectKeyNavigation::last() { ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram ); ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection() ) ); bool bResult = !aSiblings.empty(); if( bResult ) setCurrentSelection( aSiblings.back()); else bResult = veryLast(); return bResult; } bool ObjectKeyNavigation::next() { ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram ); ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection() ) ); bool bResult = !aSiblings.empty(); if( bResult ) { ObjectHierarchy::tChildContainer::const_iterator aIt( ::std::find( aSiblings.begin(), aSiblings.end(), getCurrentSelection())); OSL_ASSERT( aIt != aSiblings.end()); if( ++aIt == aSiblings.end()) aIt = aSiblings.begin(); setCurrentSelection( *aIt ); } else bResult = veryFirst(); return bResult; } bool ObjectKeyNavigation::previous() { ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram ); ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection())); bool bResult = !aSiblings.empty(); if( bResult ) { ObjectHierarchy::tChildContainer::const_iterator aIt( ::std::find( aSiblings.begin(), aSiblings.end(), getCurrentSelection())); OSL_ASSERT( aIt != aSiblings.end()); if( aIt == aSiblings.begin()) aIt = aSiblings.end(); --aIt; setCurrentSelection( *aIt ); } else bResult = veryLast(); return bResult; } bool ObjectKeyNavigation::up() { ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram ); bool bResult = !ObjectHierarchy::isRootNode( getCurrentSelection()); if( bResult ) setCurrentSelection( aHierarchy.getParent( getCurrentSelection())); return bResult; } bool ObjectKeyNavigation::down() { ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram ); bool bResult = aHierarchy.hasChildren( getCurrentSelection()); if( bResult ) { ObjectHierarchy::tChildContainer aChildren = aHierarchy.getChildren( getCurrentSelection()); OSL_ASSERT( !aChildren.empty()); setCurrentSelection( aChildren.front()); } return bResult; } bool ObjectKeyNavigation::veryFirst() { ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram ); ObjectHierarchy::tChildContainer aChildren( aHierarchy.getTopLevelChildren()); bool bResult = !aChildren.empty(); if( bResult ) setCurrentSelection( aChildren.front()); return bResult; } bool ObjectKeyNavigation::veryLast() { ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram ); ObjectHierarchy::tChildContainer aChildren( aHierarchy.getTopLevelChildren()); bool bResult = !aChildren.empty(); if( bResult ) setCurrentSelection( aChildren.back()); return bResult; } } // namespace chart