merged tag ooo/OOO330_m14
[LibreOffice.git] / chart2 / source / tools / RangeHighlighter.cxx
blob1565344923b1b7d2bca0cee07a7006b319ab50b8
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"
36 #include "macros.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;
52 namespace
55 void lcl_fillRanges(
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
73 namespace chart
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
116 OUString aCID;
117 aSelection >>= aCID;
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 )
134 // Data Point
135 fillRangesForDataPoint( xDataSeries, nIndex );
136 return;
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 );
143 return;
145 else if( xDataSeries.is() )
147 // Data Series
148 fillRangesForDataSeries( xDataSeries );
149 return;
151 else if( OBJECTTYPE_AXIS == eObjectType )
153 // Axis (Categories)
154 Reference< chart2::XAxis > xAxis( ObjectIdentifier::getObjectPropertySet( aCID, xChartModel ), uno::UNO_QUERY );
155 if( xAxis.is())
157 fillRangesForCategories( xAxis );
158 return;
161 else if( OBJECTTYPE_PAGE == eObjectType
162 || OBJECTTYPE_DIAGRAM == eObjectType
163 || OBJECTTYPE_DIAGRAM_WALL == eObjectType
164 || OBJECTTYPE_DIAGRAM_FLOOR == eObjectType
167 // Diagram
168 Reference< chart2::XDiagram > xDia( ObjectIdentifier::getDiagramForCID( aCID, xChartModel ) );
169 if( xDia.is())
171 fillRangesForDiagram( xDia );
172 return;
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;
182 if ( xShape.is() )
184 return;
187 else
189 //if nothing is selected select all ranges
190 Reference< chart2::XChartDocument > xChartDoc( xChartModel, uno::UNO_QUERY_THROW );
191 fillRangesForDiagram( xChartDoc->getFirstDiagram() );
192 return;
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 );
220 if( xSource.is())
221 lcl_fillRanges( m_aSelectedRanges,
222 ::chart::DataSourceHelper::getRangesFromDataSource( xSource ),
223 nPreferredColor );
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 =
236 ( xErrorBar.is() &&
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 );
249 if( xSource.is())
250 lcl_fillRanges( m_aSelectedRanges,
251 ::chart::DataSourceHelper::getRangesFromDataSource( xSource ),
252 nPreferredColor );
254 else
256 fillRangesForDataSeries( xSeries );
260 void RangeHighlighter::fillRangesForCategories( const Reference< chart2::XAxis > & xAxis )
262 if( ! xAxis.is())
263 return;
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 );
275 if( xSource.is() )
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());
284 if( xLabel.is())
285 aHilightedRanges.push_back(
286 chart2::data::HighlightedRange(
287 xLabel->getSourceRangeRepresentation(),
289 nPreferredColor,
290 sal_False ));
292 sal_Int32 nUnhiddenIndex = DataSeriesHelper::translateIndexFromHiddenToFullSequence( nIndex, xValues, !m_bIncludeHiddenCells );
293 if( xValues.is())
294 aHilightedRanges.push_back(
295 chart2::data::HighlightedRange(
296 xValues->getSourceRangeRepresentation(),
297 nUnhiddenIndex,
298 nPreferredColor,
299 sal_False ));
301 m_aSelectedRanges = ContainerHelper::ContainerToSequence( aHilightedRanges );
306 void SAL_CALL RangeHighlighter::addSelectionChangeListener( const Reference< view::XSelectionChangeListener >& xListener )
307 throw (uno::RuntimeException)
309 if(!xListener.is())
310 return;
312 if( m_nAddedListenerCount == 0 )
313 startListening();
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 )
328 stopListening();
331 // ____ XSelectionChangeListener ____
332 void SAL_CALL RangeHighlighter::selectionChanged( const lang::EventObject& /*aEvent*/ )
333 throw (uno::RuntimeException)
335 determineRanges();
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) );
346 if( pIC )
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 );
353 if( xListener.is() )
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 ));
377 determineRanges();
379 m_xSelectionSupplier->addSelectionChangeListener( m_xListener );
383 void RangeHighlighter::stopListening()
385 if( m_xSelectionSupplier.is() && m_xListener.is())
387 m_xSelectionSupplier->removeSelectionChangeListener( m_xListener );
388 m_xListener.clear();
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
399 // stopListening();
400 m_xListener.clear();
401 m_xSelectionSupplier.clear();
402 m_nAddedListenerCount = 0;
403 m_aSelectedRanges.realloc( 0 );
406 } // namespace chart