1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_chart2.hxx"
26 #include "LegendWrapper.hxx"
27 #include "macros.hxx"
28 #include "Chart2ModelContact.hxx"
29 #include "LegendHelper.hxx"
30 #include "ContainerHelper.hxx"
31 #include <comphelper/InlineContainer.hxx>
32 #include <com/sun/star/beans/PropertyAttribute.hpp>
33 #include <com/sun/star/chart2/XTitled.hpp>
34 #include <com/sun/star/chart/ChartLegendPosition.hpp>
35 #include <com/sun/star/chart2/LegendPosition.hpp>
36 #include <com/sun/star/chart/ChartLegendExpansion.hpp>
37 #include <com/sun/star/chart2/RelativePosition.hpp>
38 #include <com/sun/star/drawing/FillStyle.hpp>
39 
40 #include "CharacterProperties.hxx"
41 #include "LineProperties.hxx"
42 #include "FillProperties.hxx"
43 #include "UserDefinedProperties.hxx"
44 #include "WrappedCharacterHeightProperty.hxx"
45 #include "PositionAndSizeHelper.hxx"
46 #include "WrappedDirectStateProperty.hxx"
47 #include "WrappedAutomaticPositionProperties.hxx"
48 #include "WrappedScaleTextProperties.hxx"
49 
50 #include <algorithm>
51 #include <rtl/ustrbuf.hxx>
52 
53 using namespace ::com::sun::star;
54 using ::com::sun::star::beans::Property;
55 using ::osl::MutexGuard;
56 using ::com::sun::star::uno::Any;
57 using ::com::sun::star::uno::Reference;
58 using ::com::sun::star::uno::Sequence;
59 
60 //-----------------------------------------------------------------------------
61 //-----------------------------------------------------------------------------
62 
63 namespace chart
64 {
65 class WrappedLegendAlignmentProperty : public WrappedProperty
66 {
67 public:
68     WrappedLegendAlignmentProperty();
69     virtual ~WrappedLegendAlignmentProperty();
70 
71     virtual void setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& xInnerPropertySet ) const
72                                     throw (beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException);
73     virtual Any getPropertyValue( const Reference< beans::XPropertySet >& xInnerPropertySet ) const
74                                     throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException);
75 
76 protected:
77     virtual Any convertInnerToOuterValue( const Any& rInnerValue ) const;
78     virtual Any convertOuterToInnerValue( const Any& rOuterValue ) const;
79 };
80 
WrappedLegendAlignmentProperty()81 WrappedLegendAlignmentProperty::WrappedLegendAlignmentProperty()
82     : ::chart::WrappedProperty( C2U( "Alignment" ), C2U( "AnchorPosition" ) )
83 {
84 }
~WrappedLegendAlignmentProperty()85 WrappedLegendAlignmentProperty::~WrappedLegendAlignmentProperty()
86 {
87 }
88 
getPropertyValue(const Reference<beans::XPropertySet> & xInnerPropertySet) const89 Any WrappedLegendAlignmentProperty::getPropertyValue( const Reference< beans::XPropertySet >& xInnerPropertySet ) const
90                         throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
91 {
92     Any aRet;
93     if( xInnerPropertySet.is() )
94     {
95         sal_Bool bShowLegend = sal_True;
96         xInnerPropertySet->getPropertyValue( C2U( "Show" ) ) >>= bShowLegend;
97         if(!bShowLegend)
98         {
99             aRet = uno::makeAny( ::com::sun::star::chart::ChartLegendPosition_NONE );
100         }
101         else
102         {
103             aRet = xInnerPropertySet->getPropertyValue( m_aInnerName );
104             aRet = this->convertInnerToOuterValue( aRet );
105         }
106     }
107     return aRet;
108 }
109 
setPropertyValue(const Any & rOuterValue,const Reference<beans::XPropertySet> & xInnerPropertySet) const110 void WrappedLegendAlignmentProperty::setPropertyValue( const Any& rOuterValue, const Reference< beans::XPropertySet >& xInnerPropertySet ) const
111                 throw (beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException)
112 {
113     if(xInnerPropertySet.is())
114     {
115         sal_Bool bNewShowLegend = sal_True;
116         sal_Bool bOldShowLegend = sal_True;
117         {
118             ::com::sun::star::chart::ChartLegendPosition eOuterPos(::com::sun::star::chart::ChartLegendPosition_NONE);
119             if( (rOuterValue >>= eOuterPos)  && eOuterPos == ::com::sun::star::chart::ChartLegendPosition_NONE )
120                 bNewShowLegend = sal_False;
121             xInnerPropertySet->getPropertyValue( C2U( "Show" ) ) >>= bOldShowLegend;
122         }
123         if(bNewShowLegend!=bOldShowLegend)
124         {
125             xInnerPropertySet->setPropertyValue( C2U( "Show" ), uno::makeAny(bNewShowLegend) );
126         }
127         if(!bNewShowLegend)
128             return;
129 
130         //set corresponding LegendPosition
131         Any aInnerValue = this->convertOuterToInnerValue( rOuterValue );
132         xInnerPropertySet->setPropertyValue( m_aInnerName, aInnerValue );
133 
134         //correct LegendExpansion
135         chart2::LegendPosition eNewInnerPos(chart2::LegendPosition_LINE_END);
136         if( aInnerValue >>= eNewInnerPos )
137         {
138             ::com::sun::star::chart::ChartLegendExpansion eNewExpansion =
139                 ( eNewInnerPos == chart2::LegendPosition_LINE_END ||
140                   eNewInnerPos == chart2::LegendPosition_LINE_START )
141                 ? ::com::sun::star::chart::ChartLegendExpansion_HIGH
142                 : ::com::sun::star::chart::ChartLegendExpansion_WIDE;
143 
144             ::com::sun::star::chart::ChartLegendExpansion eOldExpansion( ::com::sun::star::chart::ChartLegendExpansion_HIGH );
145             bool bExpansionWasSet(
146                 xInnerPropertySet->getPropertyValue( C2U( "Expansion" ) ) >>= eOldExpansion );
147 
148             if( !bExpansionWasSet || (eOldExpansion != eNewExpansion))
149                 xInnerPropertySet->setPropertyValue( C2U( "Expansion" ), uno::makeAny( eNewExpansion ));
150         }
151 
152         //correct RelativePosition
153         Any aRelativePosition( xInnerPropertySet->getPropertyValue( C2U( "RelativePosition" ) ) );
154         if(aRelativePosition.hasValue())
155         {
156             xInnerPropertySet->setPropertyValue( C2U( "RelativePosition" ), Any() );
157         }
158     }
159 }
160 
convertInnerToOuterValue(const Any & rInnerValue) const161 Any WrappedLegendAlignmentProperty::convertInnerToOuterValue( const Any& rInnerValue ) const
162 {
163     ::com::sun::star::chart::ChartLegendPosition ePos = ::com::sun::star::chart::ChartLegendPosition_NONE;
164 
165     chart2::LegendPosition eNewPos;
166     if( rInnerValue >>= eNewPos )
167     {
168         switch( eNewPos )
169         {
170             case chart2::LegendPosition_LINE_START:
171                 ePos = ::com::sun::star::chart::ChartLegendPosition_LEFT;
172                 break;
173             case chart2::LegendPosition_LINE_END:
174                 ePos = ::com::sun::star::chart::ChartLegendPosition_RIGHT;
175                 break;
176             case chart2::LegendPosition_PAGE_START:
177                 ePos = ::com::sun::star::chart::ChartLegendPosition_TOP;
178                 break;
179             case chart2::LegendPosition_PAGE_END:
180                 ePos = ::com::sun::star::chart::ChartLegendPosition_BOTTOM;
181                 break;
182 
183             default:
184                 ePos = ::com::sun::star::chart::ChartLegendPosition_NONE;
185                 break;
186         }
187     }
188     return uno::makeAny( ePos );
189 }
convertOuterToInnerValue(const Any & rOuterValue) const190 Any WrappedLegendAlignmentProperty::convertOuterToInnerValue( const Any& rOuterValue ) const
191 {
192     chart2::LegendPosition eNewPos = chart2::LegendPosition_LINE_END;
193 
194     ::com::sun::star::chart::ChartLegendPosition ePos;
195     if( rOuterValue >>= ePos )
196     {
197         switch( ePos )
198         {
199             case ::com::sun::star::chart::ChartLegendPosition_LEFT:
200                 eNewPos = chart2::LegendPosition_LINE_START;
201                 break;
202             case ::com::sun::star::chart::ChartLegendPosition_RIGHT:
203                 eNewPos = chart2::LegendPosition_LINE_END;
204                 break;
205             case ::com::sun::star::chart::ChartLegendPosition_TOP:
206                 eNewPos = chart2::LegendPosition_PAGE_START;
207                 break;
208             case ::com::sun::star::chart::ChartLegendPosition_BOTTOM:
209                 eNewPos = chart2::LegendPosition_PAGE_END;
210                 break;
211             default: // NONE
212                 break;
213         }
214     }
215 
216     return uno::makeAny( eNewPos );
217 }
218 }
219 //-----------------------------------------------------------------------------
220 //-----------------------------------------------------------------------------
221 //-----------------------------------------------------------------------------
222 //-----------------------------------------------------------------------------
223 
224 namespace
225 {
226 static const ::rtl::OUString lcl_aServiceName(
227     RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart.Legend" ));
228 
229 enum
230 {
231     PROP_LEGEND_ALIGNMENT,
232     PROP_LEGEND_EXPANSION
233 };
234 
lcl_AddPropertiesToVector(::std::vector<Property> & rOutProperties)235 void lcl_AddPropertiesToVector(
236     ::std::vector< Property > & rOutProperties )
237 {
238     rOutProperties.push_back(
239         Property( C2U( "Alignment" ),
240                   PROP_LEGEND_ALIGNMENT,
241                   ::getCppuType( reinterpret_cast< const ::com::sun::star::chart::ChartLegendPosition * >(0)),
242                   //#i111967# no PropertyChangeEvent is fired on change so far
243                   beans::PropertyAttribute::MAYBEDEFAULT ));
244 
245     rOutProperties.push_back(
246         Property( C2U( "Expansion" ),
247                   PROP_LEGEND_EXPANSION,
248                   ::getCppuType( reinterpret_cast< const ::com::sun::star::chart::ChartLegendExpansion * >(0)),
249                   //#i111967# no PropertyChangeEvent is fired on change so far
250                   beans::PropertyAttribute::MAYBEDEFAULT ));
251 }
252 
253 struct StaticLegendWrapperPropertyArray_Initializer
254 {
operator ()__anon4e210bca0111::StaticLegendWrapperPropertyArray_Initializer255     Sequence< Property >* operator()()
256     {
257         static Sequence< Property > aPropSeq( lcl_GetPropertySequence() );
258         return &aPropSeq;
259     }
260 
261 private:
lcl_GetPropertySequence__anon4e210bca0111::StaticLegendWrapperPropertyArray_Initializer262     Sequence< Property > lcl_GetPropertySequence()
263     {
264         ::std::vector< ::com::sun::star::beans::Property > aProperties;
265         lcl_AddPropertiesToVector( aProperties );
266         ::chart::CharacterProperties::AddPropertiesToVector( aProperties );
267         ::chart::LineProperties::AddPropertiesToVector( aProperties );
268         ::chart::FillProperties::AddPropertiesToVector( aProperties );
269         //::chart::NamedProperties::AddPropertiesToVector( aProperties );
270         ::chart::UserDefinedProperties::AddPropertiesToVector( aProperties );
271         ::chart::wrapper::WrappedAutomaticPositionProperties::addProperties( aProperties );
272         ::chart::wrapper::WrappedScaleTextProperties::addProperties( aProperties );
273 
274         ::std::sort( aProperties.begin(), aProperties.end(),
275                      ::chart::PropertyNameLess() );
276 
277         return ::chart::ContainerHelper::ContainerToSequence( aProperties );
278     }
279 };
280 
281 struct StaticLegendWrapperPropertyArray : public rtl::StaticAggregate< Sequence< Property >, StaticLegendWrapperPropertyArray_Initializer >
282 {
283 };
284 
285 } // anonymous namespace
286 
287 // --------------------------------------------------------------------------------
288 // --------------------------------------------------------------------------------
289 
290 namespace chart
291 {
292 namespace wrapper
293 {
294 
LegendWrapper(::boost::shared_ptr<Chart2ModelContact> spChart2ModelContact)295 LegendWrapper::LegendWrapper( ::boost::shared_ptr< Chart2ModelContact > spChart2ModelContact ) :
296         m_spChart2ModelContact( spChart2ModelContact ),
297         m_aEventListenerContainer( m_aMutex )
298 {
299 }
300 
~LegendWrapper()301 LegendWrapper::~LegendWrapper()
302 {
303 }
304 
305 // ____ XShape ____
getPosition()306 awt::Point SAL_CALL LegendWrapper::getPosition()
307     throw (uno::RuntimeException)
308 {
309     return m_spChart2ModelContact->GetLegendPosition();
310 }
311 
setPosition(const awt::Point & aPosition)312 void SAL_CALL LegendWrapper::setPosition( const awt::Point& aPosition )
313     throw (uno::RuntimeException)
314 {
315     Reference< beans::XPropertySet > xProp( this->getInnerPropertySet() );
316     if( xProp.is() )
317     {
318         awt::Size aPageSize( m_spChart2ModelContact->GetPageSize() );
319 
320         chart2::RelativePosition aRelativePosition;
321         aRelativePosition.Anchor = drawing::Alignment_TOP_LEFT;
322         aRelativePosition.Primary = double(aPosition.X)/double(aPageSize.Width);
323         aRelativePosition.Secondary = double(aPosition.Y)/double(aPageSize.Height);
324         xProp->setPropertyValue( C2U( "RelativePosition" ), uno::makeAny(aRelativePosition) );
325     }
326 }
327 
getSize()328 awt::Size SAL_CALL LegendWrapper::getSize()
329     throw (uno::RuntimeException)
330 {
331     return m_spChart2ModelContact->GetLegendSize();
332 }
333 
setSize(const awt::Size & aSize)334 void SAL_CALL LegendWrapper::setSize( const awt::Size& aSize )
335     throw (beans::PropertyVetoException,
336            uno::RuntimeException)
337 {
338     Reference< beans::XPropertySet > xProp( this->getInnerPropertySet() );
339     if( xProp.is() )
340     {
341         awt::Size aPageSize( m_spChart2ModelContact->GetPageSize() );
342         awt::Rectangle aPageRectangle( 0,0,aPageSize.Width,aPageSize.Height);
343 
344         awt::Point aPos( this->getPosition() );
345         awt::Rectangle aNewPositionAndSize(aPos.X,aPos.Y,aSize.Width,aSize.Height);
346 
347         PositionAndSizeHelper::moveObject( OBJECTTYPE_LEGEND
348                 , xProp, aNewPositionAndSize, aPageRectangle );
349     }
350 }
351 
352 // ____ XShapeDescriptor (base of XShape) ____
getShapeType()353 ::rtl::OUString SAL_CALL LegendWrapper::getShapeType()
354     throw (uno::RuntimeException)
355 {
356     return C2U( "com.sun.star.chart.ChartLegend" );
357 }
358 
359 // ____ XComponent ____
dispose()360 void SAL_CALL LegendWrapper::dispose()
361     throw (uno::RuntimeException)
362 {
363     Reference< uno::XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) );
364     m_aEventListenerContainer.disposeAndClear( lang::EventObject( xSource ) );
365 
366     // /--
367     MutexGuard aGuard( GetMutex());
368     clearWrappedPropertySet();
369     // \--
370 }
371 
addEventListener(const Reference<lang::XEventListener> & xListener)372 void SAL_CALL LegendWrapper::addEventListener(
373     const Reference< lang::XEventListener >& xListener )
374     throw (uno::RuntimeException)
375 {
376 	m_aEventListenerContainer.addInterface( xListener );
377 }
378 
removeEventListener(const Reference<lang::XEventListener> & aListener)379 void SAL_CALL LegendWrapper::removeEventListener(
380     const Reference< lang::XEventListener >& aListener )
381     throw (uno::RuntimeException)
382 {
383 	m_aEventListenerContainer.removeInterface( aListener );
384 }
385 
386 // ================================================================================
387 
388 //ReferenceSizePropertyProvider
updateReferenceSize()389 void LegendWrapper::updateReferenceSize()
390 {
391     Reference< beans::XPropertySet > xProp( this->getInnerPropertySet(), uno::UNO_QUERY );
392     if( xProp.is() )
393     {
394         if( xProp->getPropertyValue( C2U("ReferencePageSize") ).hasValue() )
395             xProp->setPropertyValue( C2U("ReferencePageSize"), uno::makeAny(
396                 m_spChart2ModelContact->GetPageSize() ));
397     }
398 }
getReferenceSize()399 Any LegendWrapper::getReferenceSize()
400 {
401     Any aRet;
402     Reference< beans::XPropertySet > xProp( this->getInnerPropertySet(), uno::UNO_QUERY );
403     if( xProp.is() )
404         aRet = xProp->getPropertyValue( C2U("ReferencePageSize") );
405 
406     return aRet;
407 }
getCurrentSizeForReference()408 awt::Size LegendWrapper::getCurrentSizeForReference()
409 {
410     return m_spChart2ModelContact->GetPageSize();
411 }
412 
413 // ================================================================================
414 
415 // WrappedPropertySet
getInnerPropertySet()416 Reference< beans::XPropertySet > LegendWrapper::getInnerPropertySet()
417 {
418     Reference< beans::XPropertySet > xRet;
419     Reference< chart2::XDiagram > xDiagram( m_spChart2ModelContact->getChart2Diagram() );
420     if( xDiagram.is() )
421         xRet.set( xDiagram->getLegend(), uno::UNO_QUERY );
422     OSL_ENSURE(xRet.is(),"LegendWrapper::getInnerPropertySet() is NULL");
423     return xRet;
424 }
425 
getPropertySequence()426 const Sequence< beans::Property >& LegendWrapper::getPropertySequence()
427 {
428     return *StaticLegendWrapperPropertyArray::get();
429 }
430 
createWrappedProperties()431 const std::vector< WrappedProperty* > LegendWrapper::createWrappedProperties()
432 {
433     ::std::vector< ::chart::WrappedProperty* > aWrappedProperties;
434 
435     aWrappedProperties.push_back( new WrappedLegendAlignmentProperty() );
436     aWrappedProperties.push_back( new WrappedProperty( C2U("Expansion"), C2U("Expansion") ));
437     WrappedCharacterHeightProperty::addWrappedProperties( aWrappedProperties, this );
438     //same problem as for wall: thje defaults ion the old chart are different for different charttypes, so we need to export explicitly
439     aWrappedProperties.push_back( new WrappedDirectStateProperty( C2U("FillStyle"), C2U("FillStyle") ) );
440     aWrappedProperties.push_back( new WrappedDirectStateProperty( C2U("FillColor"), C2U("FillColor") ));
441     WrappedAutomaticPositionProperties::addWrappedProperties( aWrappedProperties );
442     WrappedScaleTextProperties::addWrappedProperties( aWrappedProperties, m_spChart2ModelContact );
443 
444     return aWrappedProperties;
445 }
446 
447 // ================================================================================
448 
getSupportedServiceNames_Static()449 Sequence< ::rtl::OUString > LegendWrapper::getSupportedServiceNames_Static()
450 {
451     Sequence< ::rtl::OUString > aServices( 4 );
452     aServices[ 0 ] = C2U( "com.sun.star.chart.ChartLegend" );
453     aServices[ 1 ] = C2U( "com.sun.star.drawing.Shape" );
454     aServices[ 2 ] = C2U( "com.sun.star.xml.UserDefinedAttributeSupplier" );
455     aServices[ 3 ] = C2U( "com.sun.star.style.CharacterProperties" );
456 //     aServices[ 4 ] = C2U( "com.sun.star.beans.PropertySet" );
457 //     aServices[ 5 ] = C2U( "com.sun.star.drawing.FillProperties" );
458 //     aServices[ 6 ] = C2U( "com.sun.star.drawing.LineProperties" );
459 
460     return aServices;
461 }
462 
463 // implement XServiceInfo methods basing upon getSupportedServiceNames_Static
464 APPHELPER_XSERVICEINFO_IMPL( LegendWrapper, lcl_aServiceName );
465 
466 } //  namespace wrapper
467 } //  namespace chart
468