summaryrefslogtreecommitdiff
path: root/chart2/source/controller/main/ObjectHierarchy.cxx
diff options
context:
space:
mode:
authorVladimir Glazounov <vg@openoffice.org>2007-05-22 17:08:17 +0000
committerVladimir Glazounov <vg@openoffice.org>2007-05-22 17:08:17 +0000
commit649c3c268a0574bc0657837eca97c4eda510e2fd (patch)
tree980f97cc82f538bf4c69e5af3174019bf824bb41 /chart2/source/controller/main/ObjectHierarchy.cxx
parent5998268390873aaffbf2ef8d43d4ea5df78656f2 (diff)
INTEGRATION: CWS chart2mst3 (1.1.2); FILE ADDED
2007/02/08 21:25:37 iha 1.1.2.6: resync m195 -> m202 2006/04/27 11:50:21 bm 1.1.2.5: allow flattening the diagram content in the hierarchy for keyboard navigation 2006/04/10 18:32:11 iha 1.1.2.4: api restructure axis, grids, scales and increments 2006/04/10 15:03:33 iha 1.1.2.3: api restructure axis, grids, scales and increments 2006/04/10 12:25:07 iha 1.1.2.2: api restructure axis, grids, scales and increments 2006/03/15 15:51:46 bm 1.1.2.1: moved here from tools
Diffstat (limited to 'chart2/source/controller/main/ObjectHierarchy.cxx')
-rw-r--r--chart2/source/controller/main/ObjectHierarchy.cxx708
1 files changed, 708 insertions, 0 deletions
diff --git a/chart2/source/controller/main/ObjectHierarchy.cxx b/chart2/source/controller/main/ObjectHierarchy.cxx
new file mode 100644
index 000000000000..a1b01234d59d
--- /dev/null
+++ b/chart2/source/controller/main/ObjectHierarchy.cxx
@@ -0,0 +1,708 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: ObjectHierarchy.cxx,v $
+ *
+ * $Revision: 1.2 $
+ *
+ * last change: $Author: vg $ $Date: 2007-05-22 18:08:17 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library 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 for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ************************************************************************/
+
+// 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 <map>
+#include <algorithm>
+
+#include <com/sun/star/chart2/XTitled.hpp>
+#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
+#include <com/sun/star/chart2/XChartTypeContainer.hpp>
+#include <com/sun/star/chart2/XDataSeriesContainer.hpp>
+
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/awt/Key.hpp>
+#include <com/sun/star/awt/KeyModifier.hpp>
+
+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_ObjectToCID : public ::std::unary_function< Reference< uno::XInterface >, OUString >
+{
+ explicit lcl_ObjectToCID( const Reference< chart2::XChartDocument > & xChartDoc ) :
+ m_xModel( xChartDoc, uno::UNO_QUERY )
+ {}
+
+ OUString operator() ( const Reference< uno::XInterface > & xObj )
+ {
+ return ::chart::ObjectIdentifier::createClassifiedIdentifierForObject( xObj, m_xModel );
+ }
+
+private:
+ Reference< frame::XModel > m_xModel;
+};
+
+void lcl_getChildCIDs(
+ ::chart::ObjectHierarchy::tChildContainer & rOutChildren,
+ const Reference< container::XIndexAccess > & xShapes )
+{
+ if( xShapes.is())
+ {
+ sal_Int32 nCount = xShapes->getCount();
+ for( sal_Int32 i=0; i<nCount; ++i)
+ {
+ Reference< beans::XPropertySet > 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( aName );
+ }
+ Reference< container::XIndexAccess > xNewShapes( xShapeProp, uno::UNO_QUERY );
+ if( xNewShapes.is())
+ lcl_getChildCIDs( rOutChildren, xNewShapes );
+ }
+ }
+ }
+}
+
+} // anonymous namespace
+
+
+namespace chart
+{
+
+namespace impl
+{
+class ImplObjectHierarchy
+{
+public:
+ explicit ImplObjectHierarchy(
+ const Reference< XChartDocument > & xChartDocument,
+ ExplicitValueProvider * pExplicitValueProvider,
+ bool bFlattenDiagram );
+
+ bool hasChildren( const OUString & rParent );
+ ObjectHierarchy::tChildContainer getChildren( const OUString & rParent );
+ ObjectHierarchy::tChildContainer getSiblings( const OUString & rNode );
+
+ ObjectHierarchy::tCID getParent( const ObjectHierarchy::tCID & rCID );
+
+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 );
+ ObjectHierarchy::tCID getParentImpl(
+ const ObjectHierarchy::tCID & rParentCID,
+ const ObjectHierarchy::tCID & rCID );
+
+ typedef ::std::map< OUString, 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->getTitle());
+ if( xMainTitle.is())
+ aTopLevelContainer.push_back(
+ 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->getTitle());
+ if( xSubTitle.is())
+ aTopLevelContainer.push_back(
+ ObjectIdentifier::createClassifiedIdentifierForObject( xSubTitle, xModel ));
+ }
+
+ // Axis Titles. Note: These are interpreted of being top level
+ Sequence< Reference< XAxis > > aAxes( AxisHelper::getAllAxisOfDiagram( xDiagram ) );
+ for( sal_Int32 i=0; i<aAxes.getLength(); ++i )
+ {
+ Reference< XTitled > xAxisTitled( aAxes[i], uno::UNO_QUERY );
+ if( xAxisTitled.is())
+ {
+ Reference< XTitle > xAxisTitle( xAxisTitled->getTitle());
+ if( xAxisTitle.is())
+ aTopLevelContainer.push_back(
+ ObjectIdentifier::createClassifiedIdentifierForObject( xAxisTitle, xModel ));
+ }
+ }
+
+ // Diagram
+ OUString aDiaCID( ObjectIdentifier::createClassifiedIdentifierForObject( xDiagram, xModel ));
+ OSL_ASSERT( aDiaCID.getLength());
+ aTopLevelContainer.push_back( aDiaCID );
+ if( m_bFlattenDiagram )
+ createDiagramTree( aTopLevelContainer, xChartDocument, xDiagram );
+ else
+ {
+ ObjectHierarchy::tChildContainer aSubContainer;
+ createDiagramTree( aSubContainer, xChartDocument, xDiagram );
+ if( ! aSubContainer.empty())
+ m_aChildMap[ aDiaCID ] = 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 )
+ {
+ OUString aLegendCID( ObjectIdentifier::createClassifiedIdentifierForObject( xLegend, xModel ));
+ aTopLevelContainer.push_back( aLegendCID );
+
+ // iterate over child shapes of legend and search for matching CIDs
+ if( m_pExplicitValueProvider )
+ {
+ Reference< container::XIndexAccess > xLegendShapeContainer(
+ m_pExplicitValueProvider->getShapeForCID( aLegendCID ), uno::UNO_QUERY );
+ ObjectHierarchy::tChildContainer aLegendEntryCIDs;
+ lcl_getChildCIDs( aLegendEntryCIDs, xLegendShapeContainer );
+
+ m_aChildMap[ aLegendCID ] = aLegendEntryCIDs;
+ }
+ }
+ }
+ }
+
+ // Chart Area
+ aTopLevelContainer.push_back(
+ ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, OUString() ) );
+
+ if( ! aTopLevelContainer.empty())
+ m_aChildMap[ ObjectHierarchy::getRootNodeCID() ] = 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
+ Sequence< Reference< XAxis > > aAxes( AxisHelper::getAllAxisOfDiagram( xDiagram ) );
+ ::std::transform( aAxes.getConstArray(), aAxes.getConstArray() + aAxes.getLength(),
+ ::std::back_inserter( rContainer ),
+ lcl_ObjectToCID( xChartDoc ));
+
+ // Grids
+ Reference< frame::XModel > xChartModel( xChartDoc, uno::UNO_QUERY );
+ for( sal_Int32 nA=0; nA<aAxes.getLength(); ++nA )
+ {
+ Reference< XAxis > xAxis( aAxes[nA] );
+ if(!xAxis.is())
+ continue;
+
+ Reference< beans::XPropertySet > xGridProperties( xAxis->getGridProperties() );
+ if( AxisHelper::isGridVisible( xGridProperties ) )
+ {
+ //main grid
+ rContainer.push_back(
+ 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::createClassifiedIdentifierForGrid( xAxis, xChartModel, nSubGrid ) );
+ }
+ }
+ }
+
+ // Wall
+ rContainer.push_back(
+ ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, rtl::OUString()));
+
+ // Floor
+ if( DiagramHelper::getDimension( xDiagram ) == 3 )
+ {
+ Reference< beans::XPropertySet > xFloor( xDiagram->getFloor());
+ if( xFloor.is())
+ rContainer.push_back(
+ 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<aCooSysSeq.getLength(); ++nCooSysIdx )
+ {
+ Reference< XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW );
+ Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes());
+ for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypeSeq.getLength(); ++nCTIdx )
+ {
+ Reference< XDataSeriesContainer > xDSCnt( aChartTypeSeq[nCTIdx], uno::UNO_QUERY_THROW );
+ Sequence< Reference< XDataSeries > > aSeriesSeq( xDSCnt->getDataSeries() );
+ for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeriesSeq.getLength(); ++nSeriesIdx )
+ {
+ OUString aSeriesParticle(
+ ObjectIdentifier::createParticleForSeries(
+ nDiagramIndex, nCooSysIdx, nCTIdx, nSeriesIdx ));
+ ObjectHierarchy::tCID aSeriesCID(
+ ObjectIdentifier::createClassifiedIdentifierForParticle( aSeriesParticle ));
+ rOutDiagramSubContainer.push_back( aSeriesCID );
+
+ ObjectHierarchy::tChildContainer aSeriesSubContainer;
+
+ // Statistics
+ Reference< chart2::XRegressionCurveContainer > xCurveCnt( aSeriesSeq[nSeriesIdx], uno::UNO_QUERY );
+ if( xCurveCnt.is())
+ {
+ Sequence< Reference< chart2::XRegressionCurve > > aCurves( xCurveCnt->getRegressionCurves());
+ for( sal_Int32 nCurveIdx=0; nCurveIdx<aCurves.getLength(); ++nCurveIdx )
+ {
+ bool bIsAverageLine = RegressionCurveHelper::isMeanValueLine( aCurves[nCurveIdx] );
+ aSeriesSubContainer.push_back(
+ ObjectIdentifier::createDataCurveCID( aSeriesParticle, nCurveIdx, bIsAverageLine ));
+ }
+ Reference< beans::XPropertySet > xSeriesProp( aSeriesSeq[nSeriesIdx], uno::UNO_QUERY );
+ Reference< beans::XPropertySet > xErrorBarProp;
+ if( xSeriesProp.is() &&
+ (xSeriesProp->getPropertyValue( C2U("ErrorBarY")) >>= xErrorBarProp) &&
+ xErrorBarProp.is())
+ {
+ aSeriesSubContainer.push_back(
+ 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( aSeriesCID ), uno::UNO_QUERY );
+ lcl_getChildCIDs( aSeriesSubContainer, xSeriesShapeContainer );
+ }
+
+ if( ! aSeriesSubContainer.empty())
+ m_aChildMap[ aSeriesCID ] = aSeriesSubContainer;
+ }
+ }
+ }
+ }
+ catch( uno::Exception & ex )
+ {
+ ASSERT_EXCEPTION( ex );
+ }
+}
+
+bool ImplObjectHierarchy::hasChildren( const OUString & rParent )
+{
+ if( rParent.getLength())
+ {
+ tChildMap::const_iterator aIt( m_aChildMap.find( rParent ));
+ if( aIt != m_aChildMap.end())
+ return ! (aIt->second.empty());
+ }
+ return false;
+}
+
+ObjectHierarchy::tChildContainer ImplObjectHierarchy::getChildren( const OUString & rParent )
+{
+ if( rParent.getLength())
+ {
+ tChildMap::const_iterator aIt( m_aChildMap.find( rParent ));
+ if( aIt != m_aChildMap.end())
+ return aIt->second;
+ }
+ return ObjectHierarchy::tChildContainer();
+}
+
+ObjectHierarchy::tChildContainer ImplObjectHierarchy::getSiblings( const OUString & rNode )
+{
+ if( rNode.getLength() && !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::tCID ImplObjectHierarchy::getParentImpl(
+ const ObjectHierarchy::tCID & rParentCID,
+ const ObjectHierarchy::tCID & rCID )
+{
+ // search children
+ ObjectHierarchy::tChildContainer aChildren( getChildren( rParentCID ));
+ ObjectHierarchy::tChildContainer::const_iterator aIt(
+ ::std::find( aChildren.begin(), aChildren.end(), rCID ));
+ // recursion end
+ if( aIt != aChildren.end())
+ return rParentCID;
+
+ for( aIt = aChildren.begin(); aIt != aChildren.end(); ++aIt )
+ {
+ // recursion
+ ObjectHierarchy::tCID aTempParent( getParentImpl( *aIt, rCID ));
+ if( aTempParent.getLength())
+ {
+ // exit on success
+ return aTempParent;
+ }
+ }
+
+ // exit on fail
+ return ObjectHierarchy::tCID();
+}
+
+ObjectHierarchy::tCID ImplObjectHierarchy::getParent(
+ const ObjectHierarchy::tCID & rCID )
+{
+ return getParentImpl( ObjectHierarchy::getRootNodeCID(), rCID );
+}
+
+} // 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::tCID ObjectHierarchy::getRootNodeCID()
+{
+ return C2U("ROOT");
+}
+
+// static
+bool ObjectHierarchy::isRootNode( const ObjectHierarchy::tCID & rCID )
+{
+ return rCID.equals( ObjectHierarchy::getRootNodeCID());
+}
+
+ObjectHierarchy::tChildContainer ObjectHierarchy::getTopLevelChildren() const
+{
+ return m_apImpl->getChildren( ObjectHierarchy::getRootNodeCID());
+}
+
+bool ObjectHierarchy::hasChildren( const tCID & rParent ) const
+{
+ return m_apImpl->hasChildren( rParent );
+}
+
+ObjectHierarchy::tChildContainer ObjectHierarchy::getChildren(
+ const ObjectHierarchy::tCID & rParent ) const
+{
+ if( rParent.getLength())
+ return m_apImpl->getChildren( rParent );
+
+ return ObjectHierarchy::tChildContainer();
+}
+
+ObjectHierarchy::tChildContainer ObjectHierarchy::getSiblings(
+ const ObjectHierarchy::tCID & rNode ) const
+{
+ if( rNode.getLength() && !isRootNode( rNode ))
+ return m_apImpl->getSiblings( rNode );
+
+ return ObjectHierarchy::tChildContainer();
+}
+
+ObjectHierarchy::tCID ObjectHierarchy::getParent(
+ const ObjectHierarchy::tCID & rNode ) const
+{
+ return m_apImpl->getParent( rNode );
+}
+
+sal_Int32 ObjectHierarchy::getIndexInParent(
+ const ObjectHierarchy::tCID & rNode ) const
+{
+ tCID aParentCID( m_apImpl->getParent( rNode ));
+ tChildContainer aChildren( m_apImpl->getChildren( aParentCID ));
+ tChildContainer::const_iterator aIt( aChildren.begin());
+ for( sal_Int32 nIndex = 0; aIt != aChildren.end(); ++nIndex, ++aIt )
+ {
+ if( aIt->equals( rNode ))
+ return nIndex;
+ }
+ return -1;
+}
+
+// ================================================================================
+
+ObjectKeyNavigation::ObjectKeyNavigation(
+ const ObjectHierarchy::tCID & rCurrentCID,
+ const Reference< chart2::XChartDocument > & xChartDocument,
+ ExplicitValueProvider * pExplicitValueProvider /* = 0 */ ) :
+ m_aCurrentCID( rCurrentCID ),
+ m_xChartDocument( xChartDocument ),
+ m_pExplicitValueProvider( pExplicitValueProvider ),
+ m_bStepDownInDiagram( true )
+{
+ if( m_aCurrentCID.getLength() == 0 )
+ setCurrentSelection( ObjectHierarchy::getRootNodeCID());
+}
+
+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( OUString());
+ bResult = true;
+ break;
+ default:
+ bResult = false;
+ break;
+ }
+ return bResult;
+}
+
+void ObjectKeyNavigation::setCurrentSelection( const ObjectHierarchy::tCID & rCID )
+{
+ m_aCurrentCID = rCID;
+}
+
+ObjectHierarchy::tCID ObjectKeyNavigation::getCurrentSelection() const
+{
+ return m_aCurrentCID;
+}
+
+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