1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 "RangeHighlighter.hxx"
21 #include "WeakListenerAdapter.hxx"
22 #include "ChartModelHelper.hxx"
23 #include "DataSourceHelper.hxx"
24 #include "ContainerHelper.hxx"
26 #include "ObjectIdentifier.hxx"
27 #include "DataSeriesHelper.hxx"
29 #include <com/sun/star/chart2/XDataSeries.hpp>
30 #include <com/sun/star/chart/ErrorBarStyle.hpp>
31 #include <com/sun/star/drawing/XShape.hpp>
33 #define PREFERED_DEFAULT_COLOR 0x0000ff
35 using namespace ::com::sun::star
;
37 using ::com::sun::star::uno::Reference
;
38 using ::com::sun::star::uno::Sequence
;
44 Sequence
< chart2::data::HighlightedRange
> & rOutRanges
,
45 const Sequence
< OUString
>& aRangeStrings
,
46 sal_Int32 nPreferredColor
= PREFERED_DEFAULT_COLOR
,
47 sal_Int32 nIndex
= -1 )
49 rOutRanges
.realloc( aRangeStrings
.getLength());
50 for( sal_Int32 i
=0; i
<aRangeStrings
.getLength(); ++i
)
52 rOutRanges
[i
].RangeRepresentation
= aRangeStrings
[i
];
53 rOutRanges
[i
].PreferredColor
= nPreferredColor
;
54 rOutRanges
[i
].AllowMerginigWithOtherRanges
= sal_False
;
55 rOutRanges
[i
].Index
= nIndex
;
59 } // anonymous namespace
64 RangeHighlighter::RangeHighlighter(
65 const Reference
< view::XSelectionSupplier
> & xSelectionSupplier
) :
66 impl::RangeHighlighter_Base( m_aMutex
),
67 m_xSelectionSupplier( xSelectionSupplier
),
68 m_nAddedListenerCount( 0 ),
69 m_bIncludeHiddenCells(true)
73 RangeHighlighter::~RangeHighlighter()
76 // ____ XRangeHighlighter ____
77 Sequence
< chart2::data::HighlightedRange
> SAL_CALL
RangeHighlighter::getSelectedRanges()
78 throw (uno::RuntimeException
, std::exception
)
80 return m_aSelectedRanges
;
83 void RangeHighlighter::determineRanges()
85 m_aSelectedRanges
.realloc( 0 );
86 if( m_xSelectionSupplier
.is())
90 Reference
< frame::XController
> xController( m_xSelectionSupplier
, uno::UNO_QUERY
);
91 Reference
< frame::XModel
> xChartModel
;
93 xChartModel
.set( xController
->getModel());
95 m_bIncludeHiddenCells
= ChartModelHelper::isIncludeHiddenCells( xChartModel
);
97 uno::Any
aSelection( m_xSelectionSupplier
->getSelection());
98 const uno::Type
& rType
= aSelection
.getValueType();
100 if ( rType
== cppu::UnoType
<OUString
>::get() )
102 // @todo??: maybe getSelection() should return a model object rather than a CID
106 if ( !aCID
.isEmpty() )
108 ObjectType eObjectType
= ObjectIdentifier::getObjectType( aCID
);
109 sal_Int32 nIndex
= ObjectIdentifier::getIndexFromParticleOrCID( aCID
);
110 Reference
< chart2::XDataSeries
> xDataSeries( ObjectIdentifier::getDataSeriesForCID( aCID
, xChartModel
) );
111 if( OBJECTTYPE_LEGEND_ENTRY
== eObjectType
)
113 OUString
aParentParticel( ObjectIdentifier::getFullParentParticle( aCID
) );
114 ObjectType eParentObjectType
= ObjectIdentifier::getObjectType( aParentParticel
);
115 eObjectType
= eParentObjectType
;
116 if( OBJECTTYPE_DATA_POINT
== eObjectType
)
117 nIndex
= ObjectIdentifier::getIndexFromParticleOrCID( aParentParticel
);
120 if( OBJECTTYPE_DATA_POINT
== eObjectType
|| OBJECTTYPE_DATA_LABEL
== eObjectType
)
123 fillRangesForDataPoint( xDataSeries
, nIndex
);
126 else if( OBJECTTYPE_DATA_ERRORS_X
== eObjectType
||
127 OBJECTTYPE_DATA_ERRORS_Y
== eObjectType
||
128 OBJECTTYPE_DATA_ERRORS_Z
== eObjectType
)
130 // select error bar ranges, or data series, if the style is
131 // not set to FROM_DATA
132 fillRangesForErrorBars( ObjectIdentifier::getObjectPropertySet( aCID
, xChartModel
), xDataSeries
);
135 else if( xDataSeries
.is() )
138 fillRangesForDataSeries( xDataSeries
);
141 else if( OBJECTTYPE_AXIS
== eObjectType
)
144 Reference
< chart2::XAxis
> xAxis( ObjectIdentifier::getObjectPropertySet( aCID
, xChartModel
), uno::UNO_QUERY
);
147 fillRangesForCategories( xAxis
);
151 else if( OBJECTTYPE_PAGE
== eObjectType
152 || OBJECTTYPE_DIAGRAM
== eObjectType
153 || OBJECTTYPE_DIAGRAM_WALL
== eObjectType
154 || OBJECTTYPE_DIAGRAM_FLOOR
== eObjectType
158 Reference
< chart2::XDiagram
> xDia( ObjectIdentifier::getDiagramForCID( aCID
, xChartModel
) );
161 fillRangesForDiagram( xDia
);
167 else if ( rType
== cppu::UnoType
< drawing::XShape
>::get() )
169 // #i12587# support for shapes in chart
170 Reference
< drawing::XShape
> xShape
;
171 aSelection
>>= xShape
;
179 //if nothing is selected select all ranges
180 Reference
< chart2::XChartDocument
> xChartDoc( xChartModel
, uno::UNO_QUERY_THROW
);
181 fillRangesForDiagram( xChartDoc
->getFirstDiagram() );
185 catch( const uno::Exception
& ex
)
187 ASSERT_EXCEPTION( ex
);
192 void RangeHighlighter::fillRangesForDiagram( const Reference
< chart2::XDiagram
> & xDiagram
)
194 Sequence
< OUString
> aSelectedRanges( DataSourceHelper::getUsedDataRanges( xDiagram
));
195 m_aSelectedRanges
.realloc( aSelectedRanges
.getLength());
196 // @todo: merge ranges
197 for( sal_Int32 i
=0; i
<aSelectedRanges
.getLength(); ++i
)
199 m_aSelectedRanges
[i
].RangeRepresentation
= aSelectedRanges
[i
];
200 m_aSelectedRanges
[i
].Index
= -1;
201 m_aSelectedRanges
[i
].PreferredColor
= PREFERED_DEFAULT_COLOR
;
202 m_aSelectedRanges
[i
].AllowMerginigWithOtherRanges
= sal_True
;
206 void RangeHighlighter::fillRangesForDataSeries( const uno::Reference
< chart2::XDataSeries
> & xSeries
)
208 Reference
< chart2::data::XDataSource
> xSource( xSeries
, uno::UNO_QUERY
);
211 sal_Int32 nPreferredColor
= PREFERED_DEFAULT_COLOR
;
212 lcl_fillRanges( m_aSelectedRanges
,
213 ::chart::DataSourceHelper::getRangesFromDataSource( xSource
),
218 void RangeHighlighter::fillRangesForErrorBars(
219 const uno::Reference
< beans::XPropertySet
> & xErrorBar
,
220 const uno::Reference
< chart2::XDataSeries
> & xSeries
)
222 // only show error bar ranges, if the style is set to FROM_DATA
223 bool bUsesRangesAsErrorBars
= false;
226 sal_Int32 nStyle
= ::com::sun::star::chart::ErrorBarStyle::NONE
;
227 bUsesRangesAsErrorBars
=
229 (xErrorBar
->getPropertyValue( "ErrorBarStyle") >>= nStyle
) &&
230 nStyle
== ::com::sun::star::chart::ErrorBarStyle::FROM_DATA
);
232 catch( const uno::Exception
& ex
)
234 ASSERT_EXCEPTION( ex
);
237 if( bUsesRangesAsErrorBars
)
239 Reference
< chart2::data::XDataSource
> xSource( xErrorBar
, uno::UNO_QUERY
);
242 sal_Int32 nPreferredColor
= PREFERED_DEFAULT_COLOR
;
243 lcl_fillRanges( m_aSelectedRanges
,
244 ::chart::DataSourceHelper::getRangesFromDataSource( xSource
),
250 fillRangesForDataSeries( xSeries
);
254 void RangeHighlighter::fillRangesForCategories( const Reference
< chart2::XAxis
> & xAxis
)
258 chart2::ScaleData
aData( xAxis
->getScaleData());
259 lcl_fillRanges( m_aSelectedRanges
,
260 DataSourceHelper::getRangesFromLabeledDataSequence( aData
.Categories
));
263 void RangeHighlighter::fillRangesForDataPoint( const Reference
< uno::XInterface
> & xDataSeries
, sal_Int32 nIndex
)
265 if( xDataSeries
.is())
267 Reference
< chart2::data::XDataSource
> xSource( xDataSeries
, uno::UNO_QUERY
);
270 sal_Int32 nPreferredColor
= PREFERED_DEFAULT_COLOR
;
271 ::std::vector
< chart2::data::HighlightedRange
> aHilightedRanges
;
272 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aLSeqSeq( xSource
->getDataSequences());
273 for( sal_Int32 i
=0; i
<aLSeqSeq
.getLength(); ++i
)
275 Reference
< chart2::data::XDataSequence
> xLabel( aLSeqSeq
[i
]->getLabel());
276 Reference
< chart2::data::XDataSequence
> xValues( aLSeqSeq
[i
]->getValues());
279 aHilightedRanges
.push_back(
280 chart2::data::HighlightedRange(
281 xLabel
->getSourceRangeRepresentation(),
286 sal_Int32 nUnhiddenIndex
= DataSeriesHelper::translateIndexFromHiddenToFullSequence( nIndex
, xValues
, !m_bIncludeHiddenCells
);
288 aHilightedRanges
.push_back(
289 chart2::data::HighlightedRange(
290 xValues
->getSourceRangeRepresentation(),
295 m_aSelectedRanges
= ContainerHelper::ContainerToSequence( aHilightedRanges
);
300 void SAL_CALL
RangeHighlighter::addSelectionChangeListener( const Reference
< view::XSelectionChangeListener
>& xListener
)
301 throw (uno::RuntimeException
, std::exception
)
306 if( m_nAddedListenerCount
== 0 )
308 rBHelper
.addListener( cppu::UnoType
<decltype(xListener
)>::get(), xListener
);
309 ++m_nAddedListenerCount
;
311 //bring the new listener up to the current state
312 lang::EventObject
aEvent( static_cast< lang::XComponent
* >( this ) );
313 xListener
->selectionChanged( aEvent
);
316 void SAL_CALL
RangeHighlighter::removeSelectionChangeListener( const Reference
< view::XSelectionChangeListener
>& xListener
)
317 throw (uno::RuntimeException
, std::exception
)
319 rBHelper
.removeListener( cppu::UnoType
<decltype(xListener
)>::get(), xListener
);
320 --m_nAddedListenerCount
;
321 if( m_nAddedListenerCount
== 0 )
325 // ____ XSelectionChangeListener ____
326 void SAL_CALL
RangeHighlighter::selectionChanged( const lang::EventObject
& /*aEvent*/ )
327 throw (uno::RuntimeException
, std::exception
)
331 // determine ranges of selected view objects
332 // if changed, fire an event
333 fireSelectionEvent();
336 void RangeHighlighter::fireSelectionEvent()
338 ::cppu::OInterfaceContainerHelper
* pIC
= rBHelper
.getContainer(
339 cppu::UnoType
< view::XSelectionChangeListener
>::get() );
342 lang::EventObject
aEvent( static_cast< lang::XComponent
* >( this ) );
343 ::cppu::OInterfaceIteratorHelper
aIt( *pIC
);
344 while( aIt
.hasMoreElements() )
346 uno::Reference
< view::XSelectionChangeListener
> xListener( aIt
.next(), uno::UNO_QUERY
);
348 xListener
->selectionChanged( aEvent
);
353 void SAL_CALL
RangeHighlighter::disposing( const lang::EventObject
& Source
)
354 throw (uno::RuntimeException
, std::exception
)
356 if( Source
.Source
== m_xSelectionSupplier
)
358 m_xSelectionSupplier
.clear();
359 m_aSelectedRanges
.realloc( 0 );
360 fireSelectionEvent();
364 void RangeHighlighter::startListening()
366 if( m_xSelectionSupplier
.is())
368 if( ! m_xListener
.is())
370 m_xListener
.set( new WeakSelectionChangeListenerAdapter( this ));
373 m_xSelectionSupplier
->addSelectionChangeListener( m_xListener
);
377 void RangeHighlighter::stopListening()
379 if( m_xSelectionSupplier
.is() && m_xListener
.is())
381 m_xSelectionSupplier
->removeSelectionChangeListener( m_xListener
);
386 // ____ WeakComponentImplHelperBase ____
387 // is called when dispose() is called at this component
388 void SAL_CALL
RangeHighlighter::disposing()
390 // @todo: remove listener. Currently the controller shows an assertion
391 // because it is already disposed
394 m_xSelectionSupplier
.clear();
395 m_nAddedListenerCount
= 0;
396 m_aSelectedRanges
.realloc( 0 );
401 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */