1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_chart2.hxx"
31 #include "RangeHighlighter.hxx"
32 #include "WeakListenerAdapter.hxx"
33 #include "ChartModelHelper.hxx"
34 #include "DataSourceHelper.hxx"
35 #include "ContainerHelper.hxx"
37 #include "ObjectIdentifier.hxx"
38 #include "DataSeriesHelper.hxx"
40 #include <com/sun/star/chart2/XDataSeries.hpp>
41 #include <com/sun/star/chart/ErrorBarStyle.hpp>
42 #include <com/sun/star/drawing/XShape.hpp>
44 #define PREFERED_DEFAULT_COLOR 0x0000ff
46 using namespace ::com::sun::star
;
48 using ::com::sun::star::uno::Reference
;
49 using ::com::sun::star::uno::Sequence
;
50 using ::rtl::OUString
;
56 Sequence
< chart2::data::HighlightedRange
> & rOutRanges
,
57 Sequence
< OUString
> aRangeStrings
,
58 sal_Int32 nPreferredColor
= PREFERED_DEFAULT_COLOR
,
59 sal_Int32 nIndex
= -1 )
61 rOutRanges
.realloc( aRangeStrings
.getLength());
62 for( sal_Int32 i
=0; i
<aRangeStrings
.getLength(); ++i
)
64 rOutRanges
[i
].RangeRepresentation
= aRangeStrings
[i
];
65 rOutRanges
[i
].PreferredColor
= nPreferredColor
;
66 rOutRanges
[i
].AllowMerginigWithOtherRanges
= sal_False
;
67 rOutRanges
[i
].Index
= nIndex
;
71 } // anonymous namespace
76 RangeHighlighter::RangeHighlighter(
77 const Reference
< view::XSelectionSupplier
> & xSelectionSupplier
) :
78 impl::RangeHighlighter_Base( m_aMutex
),
79 m_xSelectionSupplier( xSelectionSupplier
),
80 m_nAddedListenerCount( 0 ),
81 m_bIncludeHiddenCells(true)
85 RangeHighlighter::~RangeHighlighter()
88 // ____ XRangeHighlighter ____
89 Sequence
< chart2::data::HighlightedRange
> SAL_CALL
RangeHighlighter::getSelectedRanges()
90 throw (uno::RuntimeException
)
92 return m_aSelectedRanges
;
95 void RangeHighlighter::determineRanges()
97 m_aSelectedRanges
.realloc( 0 );
98 if( m_xSelectionSupplier
.is())
102 Reference
< frame::XController
> xController( m_xSelectionSupplier
, uno::UNO_QUERY
);
103 Reference
< frame::XModel
> xChartModel
;
104 if( xController
.is())
105 xChartModel
.set( xController
->getModel());
107 m_bIncludeHiddenCells
= ChartModelHelper::isIncludeHiddenCells( xChartModel
);
109 uno::Any
aSelection( m_xSelectionSupplier
->getSelection());
110 const uno::Type
& rType
= aSelection
.getValueType();
112 if ( rType
== ::getCppuType( static_cast< const OUString
* >( 0 ) ) )
114 // @todo??: maybe getSelection() should return a model object rather than a CID
118 if ( aCID
.getLength() > 0 )
120 ObjectType eObjectType
= ObjectIdentifier::getObjectType( aCID
);
121 sal_Int32 nIndex
= ObjectIdentifier::getIndexFromParticleOrCID( aCID
);
122 Reference
< chart2::XDataSeries
> xDataSeries( ObjectIdentifier::getDataSeriesForCID( aCID
, xChartModel
) );
123 if( OBJECTTYPE_LEGEND_ENTRY
== eObjectType
)
125 OUString
aParentParticel( ObjectIdentifier::getFullParentParticle( aCID
) );
126 ObjectType eParentObjectType
= ObjectIdentifier::getObjectType( aParentParticel
);
127 eObjectType
= eParentObjectType
;
128 if( OBJECTTYPE_DATA_POINT
== eObjectType
)
129 nIndex
= ObjectIdentifier::getIndexFromParticleOrCID( aParentParticel
);
132 if( OBJECTTYPE_DATA_POINT
== eObjectType
|| OBJECTTYPE_DATA_LABEL
== eObjectType
)
135 fillRangesForDataPoint( xDataSeries
, nIndex
);
138 else if( OBJECTTYPE_DATA_ERRORS
== eObjectType
)
140 // select error bar ranges, or data series, if the style is
141 // not set to FROM_DATA
142 fillRangesForErrorBars( ObjectIdentifier::getObjectPropertySet( aCID
, xChartModel
), xDataSeries
);
145 else if( xDataSeries
.is() )
148 fillRangesForDataSeries( xDataSeries
);
151 else if( OBJECTTYPE_AXIS
== eObjectType
)
154 Reference
< chart2::XAxis
> xAxis( ObjectIdentifier::getObjectPropertySet( aCID
, xChartModel
), uno::UNO_QUERY
);
157 fillRangesForCategories( xAxis
);
161 else if( OBJECTTYPE_PAGE
== eObjectType
162 || OBJECTTYPE_DIAGRAM
== eObjectType
163 || OBJECTTYPE_DIAGRAM_WALL
== eObjectType
164 || OBJECTTYPE_DIAGRAM_FLOOR
== eObjectType
168 Reference
< chart2::XDiagram
> xDia( ObjectIdentifier::getDiagramForCID( aCID
, xChartModel
) );
171 fillRangesForDiagram( xDia
);
177 else if ( rType
== ::getCppuType( static_cast< const Reference
< drawing::XShape
>* >( 0 ) ) )
179 // #i12587# support for shapes in chart
180 Reference
< drawing::XShape
> xShape
;
181 aSelection
>>= xShape
;
189 //if nothing is selected select all ranges
190 Reference
< chart2::XChartDocument
> xChartDoc( xChartModel
, uno::UNO_QUERY_THROW
);
191 fillRangesForDiagram( xChartDoc
->getFirstDiagram() );
195 catch( const uno::Exception
& ex
)
197 ASSERT_EXCEPTION( ex
);
202 void RangeHighlighter::fillRangesForDiagram( const Reference
< chart2::XDiagram
> & xDiagram
)
204 Sequence
< OUString
> aSelectedRanges( DataSourceHelper::getUsedDataRanges( xDiagram
));
205 m_aSelectedRanges
.realloc( aSelectedRanges
.getLength());
206 // @todo: merge ranges
207 for( sal_Int32 i
=0; i
<aSelectedRanges
.getLength(); ++i
)
209 m_aSelectedRanges
[i
].RangeRepresentation
= aSelectedRanges
[i
];
210 m_aSelectedRanges
[i
].Index
= -1;
211 m_aSelectedRanges
[i
].PreferredColor
= PREFERED_DEFAULT_COLOR
;
212 m_aSelectedRanges
[i
].AllowMerginigWithOtherRanges
= sal_True
;
216 void RangeHighlighter::fillRangesForDataSeries( const uno::Reference
< chart2::XDataSeries
> & xSeries
)
218 sal_Int32 nPreferredColor
= PREFERED_DEFAULT_COLOR
;
219 Reference
< chart2::data::XDataSource
> xSource( xSeries
, uno::UNO_QUERY
);
221 lcl_fillRanges( m_aSelectedRanges
,
222 ::chart::DataSourceHelper::getRangesFromDataSource( xSource
),
226 void RangeHighlighter::fillRangesForErrorBars(
227 const uno::Reference
< beans::XPropertySet
> & xErrorBar
,
228 const uno::Reference
< chart2::XDataSeries
> & xSeries
)
230 // only show error bar ranges, if the style is set to FROM_DATA
231 bool bUsesRangesAsErrorBars
= false;
234 sal_Int32 nStyle
= ::com::sun::star::chart::ErrorBarStyle::NONE
;
235 bUsesRangesAsErrorBars
=
237 (xErrorBar
->getPropertyValue( C2U("ErrorBarStyle")) >>= nStyle
) &&
238 nStyle
== ::com::sun::star::chart::ErrorBarStyle::FROM_DATA
);
240 catch( const uno::Exception
& ex
)
242 ASSERT_EXCEPTION( ex
);
245 if( bUsesRangesAsErrorBars
)
247 sal_Int32 nPreferredColor
= PREFERED_DEFAULT_COLOR
;
248 Reference
< chart2::data::XDataSource
> xSource( xErrorBar
, uno::UNO_QUERY
);
250 lcl_fillRanges( m_aSelectedRanges
,
251 ::chart::DataSourceHelper::getRangesFromDataSource( xSource
),
256 fillRangesForDataSeries( xSeries
);
260 void RangeHighlighter::fillRangesForCategories( const Reference
< chart2::XAxis
> & xAxis
)
264 chart2::ScaleData
aData( xAxis
->getScaleData());
265 lcl_fillRanges( m_aSelectedRanges
,
266 DataSourceHelper::getRangesFromLabeledDataSequence( aData
.Categories
));
269 void RangeHighlighter::fillRangesForDataPoint( const Reference
< uno::XInterface
> & xDataSeries
, sal_Int32 nIndex
)
271 sal_Int32 nPreferredColor
= PREFERED_DEFAULT_COLOR
;
272 if( xDataSeries
.is())
274 Reference
< chart2::data::XDataSource
> xSource( xDataSeries
, uno::UNO_QUERY
);
277 ::std::vector
< chart2::data::HighlightedRange
> aHilightedRanges
;
278 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aLSeqSeq( xSource
->getDataSequences());
279 for( sal_Int32 i
=0; i
<aLSeqSeq
.getLength(); ++i
)
281 Reference
< chart2::data::XDataSequence
> xLabel( aLSeqSeq
[i
]->getLabel());
282 Reference
< chart2::data::XDataSequence
> xValues( aLSeqSeq
[i
]->getValues());
285 aHilightedRanges
.push_back(
286 chart2::data::HighlightedRange(
287 xLabel
->getSourceRangeRepresentation(),
292 sal_Int32 nUnhiddenIndex
= DataSeriesHelper::translateIndexFromHiddenToFullSequence( nIndex
, xValues
, !m_bIncludeHiddenCells
);
294 aHilightedRanges
.push_back(
295 chart2::data::HighlightedRange(
296 xValues
->getSourceRangeRepresentation(),
301 m_aSelectedRanges
= ContainerHelper::ContainerToSequence( aHilightedRanges
);
306 void SAL_CALL
RangeHighlighter::addSelectionChangeListener( const Reference
< view::XSelectionChangeListener
>& xListener
)
307 throw (uno::RuntimeException
)
312 if( m_nAddedListenerCount
== 0 )
314 rBHelper
.addListener( ::getCppuType( & xListener
), xListener
);
315 ++m_nAddedListenerCount
;
317 //bring the new listener up to the current state
318 lang::EventObject
aEvent( static_cast< lang::XComponent
* >( this ) );
319 xListener
->selectionChanged( aEvent
);
322 void SAL_CALL
RangeHighlighter::removeSelectionChangeListener( const Reference
< view::XSelectionChangeListener
>& xListener
)
323 throw (uno::RuntimeException
)
325 rBHelper
.removeListener( ::getCppuType( & xListener
), xListener
);
326 --m_nAddedListenerCount
;
327 if( m_nAddedListenerCount
== 0 )
331 // ____ XSelectionChangeListener ____
332 void SAL_CALL
RangeHighlighter::selectionChanged( const lang::EventObject
& /*aEvent*/ )
333 throw (uno::RuntimeException
)
337 // determine ranges of selected view objects
338 // if changed, fire an event
339 fireSelectionEvent();
342 void RangeHighlighter::fireSelectionEvent()
344 ::cppu::OInterfaceContainerHelper
* pIC
= rBHelper
.getContainer(
345 ::getCppuType((const uno::Reference
< view::XSelectionChangeListener
>*)0) );
348 lang::EventObject
aEvent( static_cast< lang::XComponent
* >( this ) );
349 ::cppu::OInterfaceIteratorHelper
aIt( *pIC
);
350 while( aIt
.hasMoreElements() )
352 uno::Reference
< view::XSelectionChangeListener
> xListener( aIt
.next(), uno::UNO_QUERY
);
354 xListener
->selectionChanged( aEvent
);
359 void SAL_CALL
RangeHighlighter::disposing( const lang::EventObject
& Source
)
360 throw (uno::RuntimeException
)
362 if( Source
.Source
== m_xSelectionSupplier
)
364 m_xSelectionSupplier
.clear();
365 m_aSelectedRanges
.realloc( 0 );
366 fireSelectionEvent();
370 void RangeHighlighter::startListening()
372 if( m_xSelectionSupplier
.is())
374 if( ! m_xListener
.is())
376 m_xListener
.set( new WeakSelectionChangeListenerAdapter( this ));
379 m_xSelectionSupplier
->addSelectionChangeListener( m_xListener
);
383 void RangeHighlighter::stopListening()
385 if( m_xSelectionSupplier
.is() && m_xListener
.is())
387 m_xSelectionSupplier
->removeSelectionChangeListener( m_xListener
);
393 // ____ WeakComponentImplHelperBase ____
394 // is called when dispose() is called at this component
395 void SAL_CALL
RangeHighlighter::disposing()
397 // @todo: remove listener. Currently the controller shows an assertion
398 // because it is already disposed
401 m_xSelectionSupplier
.clear();
402 m_nAddedListenerCount
= 0;
403 m_aSelectedRanges
.realloc( 0 );