xref: /aoo41x/main/chart2/source/view/main/VLegend.cxx (revision 9ec58d04)
1cde9e8dcSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3cde9e8dcSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4cde9e8dcSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5cde9e8dcSAndrew Rist  * distributed with this work for additional information
6cde9e8dcSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7cde9e8dcSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8cde9e8dcSAndrew Rist  * "License"); you may not use this file except in compliance
9cde9e8dcSAndrew Rist  * with the License.  You may obtain a copy of the License at
10cde9e8dcSAndrew Rist  *
11cde9e8dcSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cde9e8dcSAndrew Rist  *
13cde9e8dcSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14cde9e8dcSAndrew Rist  * software distributed under the License is distributed on an
15cde9e8dcSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16cde9e8dcSAndrew Rist  * KIND, either express or implied.  See the License for the
17cde9e8dcSAndrew Rist  * specific language governing permissions and limitations
18cde9e8dcSAndrew Rist  * under the License.
19cde9e8dcSAndrew Rist  *
20cde9e8dcSAndrew Rist  *************************************************************/
21cde9e8dcSAndrew Rist 
22cde9e8dcSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_chart2.hxx"
26cdf0e10cSrcweir #include "VLegend.hxx"
27cdf0e10cSrcweir #include "macros.hxx"
28cdf0e10cSrcweir #include "PropertyMapper.hxx"
29cdf0e10cSrcweir #include "CommonConverters.hxx"
30cdf0e10cSrcweir #include "ObjectIdentifier.hxx"
31cdf0e10cSrcweir #include "RelativePositionHelper.hxx"
32cdf0e10cSrcweir #include "ShapeFactory.hxx"
33cdf0e10cSrcweir #include "RelativeSizeHelper.hxx"
34cdf0e10cSrcweir #include "LegendEntryProvider.hxx"
35cdf0e10cSrcweir #include "chartview/DrawModelWrapper.hxx"
36cdf0e10cSrcweir #include <com/sun/star/text/XTextRange.hpp>
37cdf0e10cSrcweir #include <com/sun/star/text/WritingMode2.hpp>
38cdf0e10cSrcweir #include <com/sun/star/beans/XPropertySet.hpp>
39cdf0e10cSrcweir #include <com/sun/star/beans/XPropertyState.hpp>
40cdf0e10cSrcweir #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
41cdf0e10cSrcweir #include <com/sun/star/drawing/LineJoint.hpp>
42cdf0e10cSrcweir #include <com/sun/star/chart/ChartLegendExpansion.hpp>
43cdf0e10cSrcweir #include <com/sun/star/chart2/LegendPosition.hpp>
44cdf0e10cSrcweir #include <com/sun/star/chart2/RelativePosition.hpp>
45cdf0e10cSrcweir #include <rtl/ustrbuf.hxx>
46cdf0e10cSrcweir #include <svl/languageoptions.hxx>
47cdf0e10cSrcweir 
48cdf0e10cSrcweir #include <vector>
49cdf0e10cSrcweir #include <algorithm>
50cdf0e10cSrcweir 
51cdf0e10cSrcweir using namespace ::com::sun::star;
52cdf0e10cSrcweir using namespace ::com::sun::star::chart2;
53cdf0e10cSrcweir 
54cdf0e10cSrcweir using ::com::sun::star::uno::Reference;
55cdf0e10cSrcweir using ::com::sun::star::uno::Sequence;
56cdf0e10cSrcweir using ::rtl::OUString;
57cdf0e10cSrcweir using ::rtl::OUStringBuffer;
58cdf0e10cSrcweir 
59cdf0e10cSrcweir //.............................................................................
60cdf0e10cSrcweir namespace chart
61cdf0e10cSrcweir {
62cdf0e10cSrcweir //.............................................................................
63cdf0e10cSrcweir 
64cdf0e10cSrcweir namespace
65cdf0e10cSrcweir {
66cdf0e10cSrcweir 
67cdf0e10cSrcweir typedef ::std::pair< ::chart::tNameSequence, ::chart::tAnySequence > tPropertyValues;
68cdf0e10cSrcweir 
69cdf0e10cSrcweir typedef ::std::vector< ViewLegendEntry > tViewLegendEntryContainer;
70cdf0e10cSrcweir 
lcl_CalcViewFontSize(const Reference<beans::XPropertySet> & xProp,const awt::Size & rReferenceSize)71cdf0e10cSrcweir double lcl_CalcViewFontSize(
72cdf0e10cSrcweir     const Reference< beans::XPropertySet > & xProp,
73cdf0e10cSrcweir     const awt::Size & rReferenceSize )
74cdf0e10cSrcweir {
75cdf0e10cSrcweir     double fResult = 10.0;
76cdf0e10cSrcweir 
77cdf0e10cSrcweir     awt::Size aPropRefSize;
78cdf0e10cSrcweir     float fFontHeight( 0.0 );
79cdf0e10cSrcweir     if( xProp.is() && ( xProp->getPropertyValue( C2U( "CharHeight" )) >>= fFontHeight ))
80cdf0e10cSrcweir     {
81cdf0e10cSrcweir         fResult = fFontHeight;
82cdf0e10cSrcweir         try
83cdf0e10cSrcweir         {
84cdf0e10cSrcweir             if( (xProp->getPropertyValue( C2U( "ReferencePageSize" )) >>= aPropRefSize) &&
85cdf0e10cSrcweir                 (aPropRefSize.Height > 0))
86cdf0e10cSrcweir             {
87cdf0e10cSrcweir                 // todo: find out if asian text is really used
88cdf0e10cSrcweir //         Reference< beans::XPropertySetInfo >xInfo( xProp, uno::UNO_QUERY );
89cdf0e10cSrcweir //         float fFontHeight2 = fFontHeight;
90cdf0e10cSrcweir //         if( xInfo.is() &&
91cdf0e10cSrcweir //             xInfo->hasPropertyByName(C2U("CharHeightAsian")) &&
92cdf0e10cSrcweir //             (xProp->getPropertyValue(C2U("CharHeightAsian")) >>= fFontHeight2) &&
93cdf0e10cSrcweir //             fFontHeight2 > fFontHeight )
94cdf0e10cSrcweir //         {
95cdf0e10cSrcweir //             fFontHeight = fFontHeight2;
96cdf0e10cSrcweir //         }
97cdf0e10cSrcweir 
98cdf0e10cSrcweir //         if( xInfo.is() &&
99cdf0e10cSrcweir //             xInfo->hasPropertyByName(C2U("CharHeightComplex")) &&
100cdf0e10cSrcweir //             (xProp->getPropertyValue(C2U("CharHeightComplex")) >>= fFontHeight2) &&
101cdf0e10cSrcweir //             fFontHeight2 > fFontHeight )
102cdf0e10cSrcweir //         {
103cdf0e10cSrcweir //             fFontHeight = fFontHeight2;
104cdf0e10cSrcweir //         }
105cdf0e10cSrcweir 
106cdf0e10cSrcweir                 fResult = ::chart::RelativeSizeHelper::calculate( fFontHeight, aPropRefSize, rReferenceSize );
107cdf0e10cSrcweir             }
108cdf0e10cSrcweir         }
109cdf0e10cSrcweir         catch( const uno::Exception & ex )
110cdf0e10cSrcweir         {
111cdf0e10cSrcweir             ASSERT_EXCEPTION( ex );
112cdf0e10cSrcweir         }
113cdf0e10cSrcweir     }
114cdf0e10cSrcweir 
115cdf0e10cSrcweir     // pt -> 1/100th mm
116cdf0e10cSrcweir     return (fResult * (2540.0 / 72.0));
117cdf0e10cSrcweir }
118cdf0e10cSrcweir 
lcl_getProperties(const Reference<beans::XPropertySet> & xLegendProp,tPropertyValues & rOutLineFillProperties,tPropertyValues & rOutTextProperties,const awt::Size & rReferenceSize)119cdf0e10cSrcweir void lcl_getProperties(
120cdf0e10cSrcweir     const Reference< beans::XPropertySet > & xLegendProp,
121cdf0e10cSrcweir     tPropertyValues & rOutLineFillProperties,
122cdf0e10cSrcweir     tPropertyValues & rOutTextProperties,
123cdf0e10cSrcweir     const awt::Size & rReferenceSize )
124cdf0e10cSrcweir {
125cdf0e10cSrcweir     // Get Line- and FillProperties from model legend
126cdf0e10cSrcweir     if( xLegendProp.is())
127cdf0e10cSrcweir     {
128cdf0e10cSrcweir         // set rOutLineFillProperties
129cdf0e10cSrcweir         ::chart::tPropertyNameValueMap aLineFillValueMap;
130cdf0e10cSrcweir         ::chart::PropertyMapper::getValueMap( aLineFillValueMap, ::chart::PropertyMapper::getPropertyNameMapForFillAndLineProperties(), xLegendProp );
131cdf0e10cSrcweir 
132cdf0e10cSrcweir         aLineFillValueMap[ C2U("LineJoint") ] = uno::makeAny( drawing::LineJoint_ROUND );
133cdf0e10cSrcweir 
134cdf0e10cSrcweir         ::chart::PropertyMapper::getMultiPropertyListsFromValueMap(
135cdf0e10cSrcweir             rOutLineFillProperties.first, rOutLineFillProperties.second, aLineFillValueMap );
136cdf0e10cSrcweir 
137cdf0e10cSrcweir         // set rOutTextProperties
138cdf0e10cSrcweir         ::chart::tPropertyNameValueMap aTextValueMap;
139cdf0e10cSrcweir         ::chart::PropertyMapper::getValueMap( aTextValueMap, ::chart::PropertyMapper::getPropertyNameMapForCharacterProperties(), xLegendProp );
140cdf0e10cSrcweir 
141cdf0e10cSrcweir         drawing::TextHorizontalAdjust eHorizAdjust( drawing::TextHorizontalAdjust_LEFT );
142cdf0e10cSrcweir         aTextValueMap[ C2U("TextAutoGrowHeight") ] = uno::makeAny( sal_True );
143cdf0e10cSrcweir         aTextValueMap[ C2U("TextAutoGrowWidth") ] = uno::makeAny( sal_True );
144cdf0e10cSrcweir         aTextValueMap[ C2U("TextHorizontalAdjust") ] = uno::makeAny( eHorizAdjust );
145cdf0e10cSrcweir         aTextValueMap[ C2U("TextMaximumFrameWidth") ] = uno::makeAny( rReferenceSize.Width ); //needs to be overwritten by actual available space in the legend
146cdf0e10cSrcweir 
147cdf0e10cSrcweir         // recalculate font size
148cdf0e10cSrcweir         awt::Size aPropRefSize;
149cdf0e10cSrcweir         float fFontHeight( 0.0 );
150cdf0e10cSrcweir         if( (xLegendProp->getPropertyValue( C2U( "ReferencePageSize" )) >>= aPropRefSize) &&
151cdf0e10cSrcweir             (aPropRefSize.Height > 0) &&
152cdf0e10cSrcweir             (aTextValueMap[ C2U("CharHeight") ] >>= fFontHeight) )
153cdf0e10cSrcweir         {
154cdf0e10cSrcweir             aTextValueMap[ C2U("CharHeight") ] = uno::makeAny(
155cdf0e10cSrcweir                 static_cast< float >(
156cdf0e10cSrcweir                     ::chart::RelativeSizeHelper::calculate( fFontHeight, aPropRefSize, rReferenceSize )));
157cdf0e10cSrcweir 
158cdf0e10cSrcweir             if( aTextValueMap[ C2U("CharHeightAsian") ] >>= fFontHeight )
159cdf0e10cSrcweir             {
160cdf0e10cSrcweir                 aTextValueMap[ C2U("CharHeightAsian") ] = uno::makeAny(
161cdf0e10cSrcweir                     static_cast< float >(
162cdf0e10cSrcweir                         ::chart::RelativeSizeHelper::calculate( fFontHeight, aPropRefSize, rReferenceSize )));
163cdf0e10cSrcweir             }
164cdf0e10cSrcweir             if( aTextValueMap[ C2U("CharHeightComplex") ] >>= fFontHeight )
165cdf0e10cSrcweir             {
166cdf0e10cSrcweir                 aTextValueMap[ C2U("CharHeightComplex") ] = uno::makeAny(
167cdf0e10cSrcweir                     static_cast< float >(
168cdf0e10cSrcweir                         ::chart::RelativeSizeHelper::calculate( fFontHeight, aPropRefSize, rReferenceSize )));
169cdf0e10cSrcweir             }
170cdf0e10cSrcweir         }
171cdf0e10cSrcweir 
172cdf0e10cSrcweir         ::chart::PropertyMapper::getMultiPropertyListsFromValueMap(
173cdf0e10cSrcweir             rOutTextProperties.first, rOutTextProperties.second, aTextValueMap );
174cdf0e10cSrcweir     }
175cdf0e10cSrcweir }
176cdf0e10cSrcweir 
lcl_createTextShapes(const tViewLegendEntryContainer & rEntries,const Reference<lang::XMultiServiceFactory> & xShapeFactory,const Reference<drawing::XShapes> & xTarget,::std::vector<Reference<drawing::XShape>> & rOutTextShapes,const tPropertyValues & rTextProperties)177cdf0e10cSrcweir awt::Size lcl_createTextShapes(
178cdf0e10cSrcweir     const tViewLegendEntryContainer & rEntries,
179cdf0e10cSrcweir     const Reference< lang::XMultiServiceFactory > & xShapeFactory,
180cdf0e10cSrcweir     const Reference< drawing::XShapes > & xTarget,
181cdf0e10cSrcweir     ::std::vector< Reference< drawing::XShape > > & rOutTextShapes,
182cdf0e10cSrcweir     const tPropertyValues & rTextProperties )
183cdf0e10cSrcweir {
184cdf0e10cSrcweir     awt::Size aResult;
185cdf0e10cSrcweir 
186cdf0e10cSrcweir     for( tViewLegendEntryContainer::const_iterator aIt( rEntries.begin());
187cdf0e10cSrcweir          aIt != rEntries.end(); ++aIt )
188cdf0e10cSrcweir     {
189cdf0e10cSrcweir         try
190cdf0e10cSrcweir         {
191cdf0e10cSrcweir             // create label shape
192cdf0e10cSrcweir             Reference< drawing::XShape > xEntry(
193cdf0e10cSrcweir                 xShapeFactory->createInstance(
194cdf0e10cSrcweir                     C2U( "com.sun.star.drawing.TextShape" )), uno::UNO_QUERY_THROW );
195cdf0e10cSrcweir             xTarget->add( xEntry );
196cdf0e10cSrcweir 
197cdf0e10cSrcweir             // set label text
198cdf0e10cSrcweir             Sequence< Reference< XFormattedString > > aLabelSeq = (*aIt).aLabel;
199cdf0e10cSrcweir             for( sal_Int32 i = 0; i < aLabelSeq.getLength(); ++i )
200cdf0e10cSrcweir             {
201cdf0e10cSrcweir                 // todo: support more than one text range
202cdf0e10cSrcweir                 if( i == 1 )
203cdf0e10cSrcweir                     break;
204cdf0e10cSrcweir 
205cdf0e10cSrcweir                 Reference< text::XTextRange > xRange( xEntry, uno::UNO_QUERY );
206cdf0e10cSrcweir                 OUString aLabelString( aLabelSeq[i]->getString());
207cdf0e10cSrcweir                 // workaround for Issue #i67540#
208*9ec58d04SHerbert Dürr                 if( aLabelString.isEmpty() )
209cdf0e10cSrcweir                     aLabelString = C2U(" ");
210cdf0e10cSrcweir                 if( xRange.is())
211cdf0e10cSrcweir                     xRange->setString( aLabelString );
212cdf0e10cSrcweir 
213cdf0e10cSrcweir                 PropertyMapper::setMultiProperties(
214cdf0e10cSrcweir                     rTextProperties.first, rTextProperties.second,
215cdf0e10cSrcweir                     Reference< beans::XPropertySet >( xRange, uno::UNO_QUERY ));
216cdf0e10cSrcweir 
217cdf0e10cSrcweir                 // adapt max-extent
218cdf0e10cSrcweir                 awt::Size aCurrSize( xEntry->getSize());
219cdf0e10cSrcweir                 aResult.Width  = ::std::max( aResult.Width,  aCurrSize.Width  );
220cdf0e10cSrcweir                 aResult.Height = ::std::max( aResult.Height, aCurrSize.Height );
221cdf0e10cSrcweir             }
222cdf0e10cSrcweir 
223cdf0e10cSrcweir             rOutTextShapes.push_back( xEntry );
224cdf0e10cSrcweir         }
225cdf0e10cSrcweir         catch( uno::Exception & ex )
226cdf0e10cSrcweir         {
227cdf0e10cSrcweir             ASSERT_EXCEPTION( ex );
228cdf0e10cSrcweir         }
229cdf0e10cSrcweir     }
230cdf0e10cSrcweir 
231cdf0e10cSrcweir     return aResult;
232cdf0e10cSrcweir }
233cdf0e10cSrcweir 
lcl_collectColumnWidths(std::vector<sal_Int32> & rColumnWidths,const sal_Int32 nNumberOfRows,const sal_Int32 nNumberOfColumns,const::std::vector<Reference<drawing::XShape>> aTextShapes,sal_Int32 nSymbolPlusDistanceWidth)234cdf0e10cSrcweir void lcl_collectColumnWidths( std::vector< sal_Int32 >& rColumnWidths, const sal_Int32 nNumberOfRows, const sal_Int32 nNumberOfColumns
235cdf0e10cSrcweir                              , const ::std::vector< Reference< drawing::XShape > > aTextShapes, sal_Int32 nSymbolPlusDistanceWidth )
236cdf0e10cSrcweir {
237cdf0e10cSrcweir     rColumnWidths.clear();
238cdf0e10cSrcweir     sal_Int32 nRow = 0;
239cdf0e10cSrcweir     sal_Int32 nColumn = 0;
240cdf0e10cSrcweir     sal_Int32 nNumberOfEntries = aTextShapes.size();
241cdf0e10cSrcweir     for( ; nRow < nNumberOfRows; ++nRow )
242cdf0e10cSrcweir     {
243cdf0e10cSrcweir         for( nColumn = 0; nColumn < nNumberOfColumns; ++nColumn )
244cdf0e10cSrcweir         {
245cdf0e10cSrcweir             sal_Int32 nEntry = (nColumn + nRow * nNumberOfColumns);
246cdf0e10cSrcweir             if( nEntry < nNumberOfEntries )
247cdf0e10cSrcweir             {
248cdf0e10cSrcweir                 awt::Size aTextSize( aTextShapes[ nEntry ]->getSize() );
249cdf0e10cSrcweir                 sal_Int32 nWidth = nSymbolPlusDistanceWidth + aTextSize.Width;
250cdf0e10cSrcweir                 if( nRow==0 )
251cdf0e10cSrcweir                     rColumnWidths.push_back( nWidth );
252cdf0e10cSrcweir                 else
253cdf0e10cSrcweir                     rColumnWidths[nColumn] = ::std::max( nWidth, rColumnWidths[nColumn] );
254cdf0e10cSrcweir             }
255cdf0e10cSrcweir         }
256cdf0e10cSrcweir     }
257cdf0e10cSrcweir }
258cdf0e10cSrcweir 
lcl_collectRowHeighs(std::vector<sal_Int32> & rRowHeights,const sal_Int32 nNumberOfRows,const sal_Int32 nNumberOfColumns,const::std::vector<Reference<drawing::XShape>> aTextShapes)259cdf0e10cSrcweir void lcl_collectRowHeighs( std::vector< sal_Int32 >& rRowHeights, const sal_Int32 nNumberOfRows, const sal_Int32 nNumberOfColumns
260cdf0e10cSrcweir                           , const ::std::vector< Reference< drawing::XShape > > aTextShapes )
261cdf0e10cSrcweir {
262cdf0e10cSrcweir     // calculate maximum height for each row
263cdf0e10cSrcweir     // and collect column widths
264cdf0e10cSrcweir     rRowHeights.clear();
265cdf0e10cSrcweir     sal_Int32 nRow = 0;
266cdf0e10cSrcweir     sal_Int32 nColumn = 0;
267cdf0e10cSrcweir     sal_Int32 nNumberOfEntries = aTextShapes.size();
268cdf0e10cSrcweir     for( ; nRow < nNumberOfRows; ++nRow )
269cdf0e10cSrcweir     {
270cdf0e10cSrcweir         sal_Int32 nCurrentRowHeight = 0;
271cdf0e10cSrcweir         for( nColumn = 0; nColumn < nNumberOfColumns; ++nColumn )
272cdf0e10cSrcweir         {
273cdf0e10cSrcweir             sal_Int32 nEntry = (nColumn + nRow * nNumberOfColumns);
274cdf0e10cSrcweir             if( nEntry < nNumberOfEntries )
275cdf0e10cSrcweir             {
276cdf0e10cSrcweir                 awt::Size aTextSize( aTextShapes[ nEntry ]->getSize() );
277cdf0e10cSrcweir                 nCurrentRowHeight = ::std::max( nCurrentRowHeight, aTextSize.Height );
278cdf0e10cSrcweir             }
279cdf0e10cSrcweir         }
280cdf0e10cSrcweir         rRowHeights.push_back( nCurrentRowHeight );
281cdf0e10cSrcweir     }
282cdf0e10cSrcweir }
283cdf0e10cSrcweir 
lcl_getTextLineHeight(const std::vector<sal_Int32> & aRowHeights,const sal_Int32 nNumberOfRows,double fViewFontSize)284cdf0e10cSrcweir sal_Int32 lcl_getTextLineHeight( const std::vector< sal_Int32 >& aRowHeights, const sal_Int32 nNumberOfRows, double fViewFontSize )
285cdf0e10cSrcweir {
286cdf0e10cSrcweir     const sal_Int32 nFontHeight = static_cast< sal_Int32 >( fViewFontSize );
287cdf0e10cSrcweir     sal_Int32 nTextLineHeight = nFontHeight;
288cdf0e10cSrcweir     for( sal_Int32 nR=0; nR<nNumberOfRows; nR++ )
289cdf0e10cSrcweir     {
290cdf0e10cSrcweir         sal_Int32 nFullTextHeight = aRowHeights[ nR ];
291cdf0e10cSrcweir         if( ( nFullTextHeight / nFontHeight ) <= 1 )
292cdf0e10cSrcweir         {
293cdf0e10cSrcweir             nTextLineHeight = nFullTextHeight;//found an entry with one line-> have real text height
294cdf0e10cSrcweir             break;
295cdf0e10cSrcweir         }
296cdf0e10cSrcweir     }
297cdf0e10cSrcweir     return nTextLineHeight;
298cdf0e10cSrcweir }
299cdf0e10cSrcweir 
300cdf0e10cSrcweir //returns resulting legend size
lcl_placeLegendEntries(tViewLegendEntryContainer & rEntries,::com::sun::star::chart::ChartLegendExpansion eExpansion,bool bSymbolsLeftSide,double fViewFontSize,const awt::Size & rMaxSymbolExtent,tPropertyValues & rTextProperties,const Reference<drawing::XShapes> & xTarget,const Reference<lang::XMultiServiceFactory> & xShapeFactory,const awt::Size & rAvailableSpace)301cdf0e10cSrcweir awt::Size lcl_placeLegendEntries(
302cdf0e10cSrcweir     tViewLegendEntryContainer & rEntries,
303cdf0e10cSrcweir     ::com::sun::star::chart::ChartLegendExpansion eExpansion,
304cdf0e10cSrcweir     bool bSymbolsLeftSide,
305cdf0e10cSrcweir     double fViewFontSize,
306cdf0e10cSrcweir     const awt::Size& rMaxSymbolExtent,
307cdf0e10cSrcweir     tPropertyValues & rTextProperties,
308cdf0e10cSrcweir     const Reference< drawing::XShapes > & xTarget,
309cdf0e10cSrcweir     const Reference< lang::XMultiServiceFactory > & xShapeFactory,
310cdf0e10cSrcweir     const awt::Size & rAvailableSpace )
311cdf0e10cSrcweir {
312cdf0e10cSrcweir     bool bIsCustomSize = (eExpansion == ::com::sun::star::chart::ChartLegendExpansion_CUSTOM);
313cdf0e10cSrcweir     awt::Size aResultingLegendSize(0,0);
314cdf0e10cSrcweir     if( bIsCustomSize )
315cdf0e10cSrcweir         aResultingLegendSize = rAvailableSpace;
316cdf0e10cSrcweir 
317cdf0e10cSrcweir     // #i109336# Improve auto positioning in chart
318cdf0e10cSrcweir     sal_Int32 nXPadding = static_cast< sal_Int32 >( std::max( 100.0, fViewFontSize * 0.33 ) );
319cdf0e10cSrcweir     //sal_Int32 nXPadding = static_cast< sal_Int32 >( std::max( 200.0, fViewFontSize * 0.33 ) );
320cdf0e10cSrcweir     sal_Int32 nXOffset  = static_cast< sal_Int32 >( std::max( 100.0, fViewFontSize * 0.66 ) );
321cdf0e10cSrcweir     sal_Int32 nYPadding = static_cast< sal_Int32 >( std::max( 100.0, fViewFontSize * 0.2 ) );
322cdf0e10cSrcweir     sal_Int32 nYOffset  = static_cast< sal_Int32 >( std::max( 100.0, fViewFontSize * 0.2 ) );
323cdf0e10cSrcweir     //sal_Int32 nYOffset  = static_cast< sal_Int32 >( std::max( 230.0, fViewFontSize * 0.45 ) );
324cdf0e10cSrcweir 
325cdf0e10cSrcweir     const sal_Int32 nSymbolToTextDistance = static_cast< sal_Int32 >( std::max( 100.0, fViewFontSize * 0.22 ) );//minimum 1mm
326cdf0e10cSrcweir     const sal_Int32 nSymbolPlusDistanceWidth = rMaxSymbolExtent.Width + nSymbolToTextDistance;
327cdf0e10cSrcweir     sal_Int32 nMaxTextWidth = rAvailableSpace.Width - (2 * nXPadding) - nSymbolPlusDistanceWidth;
328cdf0e10cSrcweir     rtl::OUString aPropNameTextMaximumFrameWidth( C2U("TextMaximumFrameWidth") );
329cdf0e10cSrcweir     uno::Any* pFrameWidthAny = PropertyMapper::getValuePointer( rTextProperties.second, rTextProperties.first, aPropNameTextMaximumFrameWidth);
330cdf0e10cSrcweir     if(pFrameWidthAny)
331cdf0e10cSrcweir     {
332cdf0e10cSrcweir         if( eExpansion == ::com::sun::star::chart::ChartLegendExpansion_HIGH )
333cdf0e10cSrcweir         {
334cdf0e10cSrcweir             // limit the width of texts to 30% of the total available width
335cdf0e10cSrcweir             // #i109336# Improve auto positioning in chart
336cdf0e10cSrcweir             nMaxTextWidth = rAvailableSpace.Width * 3 / 10;
337cdf0e10cSrcweir         }
338cdf0e10cSrcweir         *pFrameWidthAny = uno::makeAny(nMaxTextWidth);
339cdf0e10cSrcweir     }
340cdf0e10cSrcweir 
341cdf0e10cSrcweir     ::std::vector< Reference< drawing::XShape > > aTextShapes;
342cdf0e10cSrcweir     awt::Size aMaxEntryExtent = lcl_createTextShapes( rEntries, xShapeFactory, xTarget, aTextShapes, rTextProperties );
343cdf0e10cSrcweir     OSL_ASSERT( aTextShapes.size() == rEntries.size());
344cdf0e10cSrcweir 
345cdf0e10cSrcweir     sal_Int32 nMaxEntryWidth = nXOffset + nSymbolPlusDistanceWidth + aMaxEntryExtent.Width;
346cdf0e10cSrcweir     sal_Int32 nMaxEntryHeight = nYOffset + aMaxEntryExtent.Height;
347cdf0e10cSrcweir     sal_Int32 nNumberOfEntries = rEntries.size();
348cdf0e10cSrcweir 
349cdf0e10cSrcweir     sal_Int32 nNumberOfColumns = 0, nNumberOfRows = 0;
350cdf0e10cSrcweir     std::vector< sal_Int32 > aColumnWidths;
351cdf0e10cSrcweir     std::vector< sal_Int32 > aRowHeights;
352cdf0e10cSrcweir 
353cdf0e10cSrcweir     sal_Int32 nTextLineHeight = static_cast< sal_Int32 >( fViewFontSize );
354cdf0e10cSrcweir 
355cdf0e10cSrcweir     // determine layout depending on LegendExpansion
356cdf0e10cSrcweir     if( eExpansion == ::com::sun::star::chart::ChartLegendExpansion_CUSTOM )
357cdf0e10cSrcweir     {
358cdf0e10cSrcweir         sal_Int32 nCurrentRow=0;
359cdf0e10cSrcweir         sal_Int32 nCurrentColumn=-1;
360cdf0e10cSrcweir         sal_Int32 nColumnCount=0;
361cdf0e10cSrcweir         sal_Int32 nMaxColumnCount=-1;
362cdf0e10cSrcweir         for( sal_Int32 nN=0; nN<static_cast<sal_Int32>(aTextShapes.size()); nN++ )
363cdf0e10cSrcweir         {
364cdf0e10cSrcweir             Reference< drawing::XShape > xShape( aTextShapes[nN] );
365cdf0e10cSrcweir             if( !xShape.is() )
366cdf0e10cSrcweir                 continue;
367cdf0e10cSrcweir             awt::Size aSize( xShape->getSize() );
368cdf0e10cSrcweir             sal_Int32 nNewWidth = aSize.Width + nSymbolPlusDistanceWidth;
369cdf0e10cSrcweir             sal_Int32 nCurrentColumnCount = aColumnWidths.size();
370cdf0e10cSrcweir 
371cdf0e10cSrcweir             //are we allowed to add a new column?
372cdf0e10cSrcweir             if( nMaxColumnCount==-1 || (nCurrentColumn+1) < nMaxColumnCount )
373cdf0e10cSrcweir             {
374cdf0e10cSrcweir                 //try add a new column
375cdf0e10cSrcweir                 nCurrentColumn++;
376cdf0e10cSrcweir                 if( nCurrentColumn < nCurrentColumnCount )
377cdf0e10cSrcweir                 {
378cdf0e10cSrcweir                     //check wether the current column width is sufficient for the new entry
379cdf0e10cSrcweir                     if( aColumnWidths[nCurrentColumn]>=nNewWidth )
380cdf0e10cSrcweir                     {
381cdf0e10cSrcweir                         //all good proceed with next entry
382cdf0e10cSrcweir                         continue;
383cdf0e10cSrcweir                     }
384cdf0e10cSrcweir                 }
385cdf0e10cSrcweir                 if( nCurrentColumn < nCurrentColumnCount )
386cdf0e10cSrcweir                     aColumnWidths[nCurrentColumn] = std::max( nNewWidth, aColumnWidths[nCurrentColumn] );
387cdf0e10cSrcweir                 else
388cdf0e10cSrcweir                     aColumnWidths.push_back(nNewWidth);
389cdf0e10cSrcweir 
390cdf0e10cSrcweir                 //do the columns still fit into the given size?
391cdf0e10cSrcweir                 nCurrentColumnCount = aColumnWidths.size();//update count
392cdf0e10cSrcweir                 sal_Int32 nSumWidth = 0;
393cdf0e10cSrcweir                 for( sal_Int32 nC=0; nC<nCurrentColumnCount; nC++ )
394cdf0e10cSrcweir                     nSumWidth += aColumnWidths[nC];
395cdf0e10cSrcweir 
396cdf0e10cSrcweir                 if( nSumWidth <= rAvailableSpace.Width || nCurrentColumnCount==1 )
397cdf0e10cSrcweir                 {
398cdf0e10cSrcweir                     //all good proceed with next entry
399cdf0e10cSrcweir                     continue;
400cdf0e10cSrcweir                 }
401cdf0e10cSrcweir                 else
402cdf0e10cSrcweir                 {
403cdf0e10cSrcweir                     //not enough space for the current amount of columns
404cdf0e10cSrcweir                     //try again with less columns
405cdf0e10cSrcweir                     nMaxColumnCount = nCurrentColumnCount-1;
406cdf0e10cSrcweir                     nN=-1;
407cdf0e10cSrcweir                     nCurrentRow=0;
408cdf0e10cSrcweir                     nCurrentColumn=-1;
409cdf0e10cSrcweir                     nColumnCount=0;
410cdf0e10cSrcweir                     aColumnWidths.clear();
411cdf0e10cSrcweir                 }
412cdf0e10cSrcweir             }
413cdf0e10cSrcweir             else
414cdf0e10cSrcweir             {
415cdf0e10cSrcweir                 //add a new row and try the same entry again
416cdf0e10cSrcweir                 nCurrentRow++;
417cdf0e10cSrcweir                 nCurrentColumn=-1;
418cdf0e10cSrcweir                 nN--;
419cdf0e10cSrcweir             }
420cdf0e10cSrcweir         }
421cdf0e10cSrcweir         nNumberOfColumns = aColumnWidths.size();
422cdf0e10cSrcweir         nNumberOfRows = nCurrentRow+1;
423cdf0e10cSrcweir 
424cdf0e10cSrcweir         //check if there is not enough space so that some entries must be removed
425cdf0e10cSrcweir         lcl_collectRowHeighs( aRowHeights, nNumberOfRows, nNumberOfColumns, aTextShapes );
426cdf0e10cSrcweir         nTextLineHeight = lcl_getTextLineHeight( aRowHeights, nNumberOfRows, fViewFontSize );
427cdf0e10cSrcweir         sal_Int32 nSumHeight = 0;
428cdf0e10cSrcweir         for( sal_Int32 nR=0; nR<nNumberOfRows; nR++ )
429cdf0e10cSrcweir             nSumHeight += aRowHeights[nR];
430cdf0e10cSrcweir         sal_Int32 nRemainingSpace = rAvailableSpace.Height - nSumHeight;
431cdf0e10cSrcweir 
432cdf0e10cSrcweir         if( nRemainingSpace<0 )
433cdf0e10cSrcweir         {
434cdf0e10cSrcweir             //remove entries that are too big
435cdf0e10cSrcweir             for( sal_Int32 nR=nNumberOfRows; nR--; )
436cdf0e10cSrcweir             {
437cdf0e10cSrcweir                 for( sal_Int32 nC=nNumberOfColumns; nC--; )
438cdf0e10cSrcweir                 {
439cdf0e10cSrcweir                     sal_Int32 nEntry = (nC + nR * nNumberOfColumns);
440cdf0e10cSrcweir                     if( nEntry < static_cast<sal_Int32>(aTextShapes.size()) )
441cdf0e10cSrcweir                     {
442cdf0e10cSrcweir                         DrawModelWrapper::removeShape( aTextShapes[nEntry] );
443cdf0e10cSrcweir                         aTextShapes.pop_back();
444cdf0e10cSrcweir                     }
445cdf0e10cSrcweir                     if( nEntry < nNumberOfEntries )
446cdf0e10cSrcweir                     {
447cdf0e10cSrcweir                         DrawModelWrapper::removeShape( rEntries[ nEntry ].aSymbol );
448cdf0e10cSrcweir                         rEntries.pop_back();
449cdf0e10cSrcweir                         nNumberOfEntries--;
450cdf0e10cSrcweir                     }
451cdf0e10cSrcweir                 }
452cdf0e10cSrcweir                 nSumHeight -= aRowHeights[nR];
453cdf0e10cSrcweir                 aRowHeights.pop_back();
454cdf0e10cSrcweir                 nRemainingSpace = rAvailableSpace.Height - nSumHeight;
455cdf0e10cSrcweir                 if( nRemainingSpace>=0 )
456cdf0e10cSrcweir                     break;
457cdf0e10cSrcweir             }
458cdf0e10cSrcweir             nNumberOfRows = static_cast<sal_Int32>(aRowHeights.size());
459cdf0e10cSrcweir         }
460cdf0e10cSrcweir         if( nRemainingSpace > 0 )
461cdf0e10cSrcweir         {
462cdf0e10cSrcweir             sal_Int32 nNormalSpacingHeight = 2*nYPadding+(nNumberOfRows-1)*nYOffset;
463cdf0e10cSrcweir             if( nRemainingSpace < nNormalSpacingHeight )
464cdf0e10cSrcweir             {
465cdf0e10cSrcweir                 //reduce spacing between the entries
466cdf0e10cSrcweir                 nYPadding = nYOffset = nRemainingSpace/(nNumberOfRows+1);
467cdf0e10cSrcweir             }
468cdf0e10cSrcweir             else
469cdf0e10cSrcweir             {
470cdf0e10cSrcweir                 //we have some space left that should be spread equally between all rows
471cdf0e10cSrcweir                 sal_Int32 nRemainingSingleSpace = (nRemainingSpace-nNormalSpacingHeight)/(nNumberOfRows+1);
472cdf0e10cSrcweir                 nYPadding += nRemainingSingleSpace;
473cdf0e10cSrcweir                 nYOffset += nRemainingSingleSpace;
474cdf0e10cSrcweir             }
475cdf0e10cSrcweir         }
476cdf0e10cSrcweir 
477cdf0e10cSrcweir         //check spacing between columns
478cdf0e10cSrcweir         sal_Int32 nSumWidth = 0;
479cdf0e10cSrcweir         for( sal_Int32 nC=0; nC<nNumberOfColumns; nC++ )
480cdf0e10cSrcweir             nSumWidth += aColumnWidths[nC];
481cdf0e10cSrcweir         nRemainingSpace = rAvailableSpace.Width - nSumWidth;
482cdf0e10cSrcweir         if( nRemainingSpace>=0 )
483cdf0e10cSrcweir         {
484cdf0e10cSrcweir             sal_Int32 nNormalSpacingWidth = 2*nXPadding+(nNumberOfColumns-1)*nXOffset;
485cdf0e10cSrcweir             if( nRemainingSpace < nNormalSpacingWidth )
486cdf0e10cSrcweir             {
487cdf0e10cSrcweir                 //reduce spacing between the entries
488cdf0e10cSrcweir                 nXPadding = nXOffset = nRemainingSpace/(nNumberOfColumns+1);
489cdf0e10cSrcweir             }
490cdf0e10cSrcweir             else
491cdf0e10cSrcweir             {
492cdf0e10cSrcweir                 //we have some space left that should be spread equally between all columns
493cdf0e10cSrcweir                 sal_Int32 nRemainingSingleSpace = (nRemainingSpace-nNormalSpacingWidth)/(nNumberOfColumns+1);
494cdf0e10cSrcweir                 nXPadding += nRemainingSingleSpace;
495cdf0e10cSrcweir                 nXOffset += nRemainingSingleSpace;
496cdf0e10cSrcweir             }
497cdf0e10cSrcweir         }
498cdf0e10cSrcweir     }
499cdf0e10cSrcweir     else if( eExpansion == ::com::sun::star::chart::ChartLegendExpansion_HIGH )
500cdf0e10cSrcweir     {
501cdf0e10cSrcweir         sal_Int32 nMaxNumberOfRows = nMaxEntryHeight
502cdf0e10cSrcweir             ? (rAvailableSpace.Height - 2*nYPadding ) / nMaxEntryHeight
503cdf0e10cSrcweir             : 0;
504cdf0e10cSrcweir 
505cdf0e10cSrcweir         nNumberOfColumns = nMaxNumberOfRows
506cdf0e10cSrcweir             ? static_cast< sal_Int32 >(
507cdf0e10cSrcweir                 ceil( static_cast< double >( nNumberOfEntries ) /
508cdf0e10cSrcweir                       static_cast< double >( nMaxNumberOfRows ) ))
509cdf0e10cSrcweir             : 0;
510cdf0e10cSrcweir         nNumberOfRows =  nNumberOfColumns
511cdf0e10cSrcweir             ? static_cast< sal_Int32 >(
512cdf0e10cSrcweir                 ceil( static_cast< double >( nNumberOfEntries ) /
513cdf0e10cSrcweir                       static_cast< double >( nNumberOfColumns ) ))
514cdf0e10cSrcweir             : 0;
515cdf0e10cSrcweir     }
516cdf0e10cSrcweir     else if( eExpansion == ::com::sun::star::chart::ChartLegendExpansion_WIDE )
517cdf0e10cSrcweir     {
518cdf0e10cSrcweir         sal_Int32 nMaxNumberOfColumns = nMaxEntryWidth
519cdf0e10cSrcweir             ? (rAvailableSpace.Width - 2*nXPadding ) / nMaxEntryWidth
520cdf0e10cSrcweir             : 0;
521cdf0e10cSrcweir 
522cdf0e10cSrcweir         nNumberOfRows = nMaxNumberOfColumns
523cdf0e10cSrcweir             ? static_cast< sal_Int32 >(
524cdf0e10cSrcweir                 ceil( static_cast< double >( nNumberOfEntries ) /
525cdf0e10cSrcweir                       static_cast< double >( nMaxNumberOfColumns ) ))
526cdf0e10cSrcweir             : 0;
527cdf0e10cSrcweir         nNumberOfColumns = nNumberOfRows
528cdf0e10cSrcweir             ? static_cast< sal_Int32 >(
529cdf0e10cSrcweir                 ceil( static_cast< double >( nNumberOfEntries ) /
530cdf0e10cSrcweir                       static_cast< double >( nNumberOfRows ) ))
531cdf0e10cSrcweir             : 0;
532cdf0e10cSrcweir     }
533cdf0e10cSrcweir     else // ::com::sun::star::chart::ChartLegendExpansion_BALANCED
534cdf0e10cSrcweir     {
535cdf0e10cSrcweir         double fAspect = nMaxEntryHeight
536cdf0e10cSrcweir             ? static_cast< double >( nMaxEntryWidth ) / static_cast< double >( nMaxEntryHeight )
537cdf0e10cSrcweir             : 0.0;
538cdf0e10cSrcweir 
539cdf0e10cSrcweir         nNumberOfRows = static_cast< sal_Int32 >(
540cdf0e10cSrcweir             ceil( sqrt( static_cast< double >( nNumberOfEntries ) * fAspect )));
541cdf0e10cSrcweir         nNumberOfColumns = nNumberOfRows
542cdf0e10cSrcweir             ? static_cast< sal_Int32 >(
543cdf0e10cSrcweir                 ceil( static_cast< double >( nNumberOfEntries ) /
544cdf0e10cSrcweir                       static_cast< double >( nNumberOfRows ) ))
545cdf0e10cSrcweir             : 0;
546cdf0e10cSrcweir     }
547cdf0e10cSrcweir 
548cdf0e10cSrcweir     if(nNumberOfRows<=0)
549cdf0e10cSrcweir         return aResultingLegendSize;
550cdf0e10cSrcweir 
551cdf0e10cSrcweir     if( eExpansion != ::com::sun::star::chart::ChartLegendExpansion_CUSTOM )
552cdf0e10cSrcweir     {
553cdf0e10cSrcweir         lcl_collectColumnWidths( aColumnWidths, nNumberOfRows, nNumberOfColumns, aTextShapes, nSymbolPlusDistanceWidth );
554cdf0e10cSrcweir         lcl_collectRowHeighs( aRowHeights, nNumberOfRows, nNumberOfColumns, aTextShapes );
555cdf0e10cSrcweir         nTextLineHeight = lcl_getTextLineHeight( aRowHeights, nNumberOfRows, fViewFontSize );
556cdf0e10cSrcweir     }
557cdf0e10cSrcweir 
558cdf0e10cSrcweir     sal_Int32 nCurrentXPos = nXPadding;
559cdf0e10cSrcweir     sal_Int32 nCurrentYPos = nYPadding;
560cdf0e10cSrcweir     if( !bSymbolsLeftSide )
561cdf0e10cSrcweir         nCurrentXPos = -nXPadding;
562cdf0e10cSrcweir 
563cdf0e10cSrcweir     // place entries into column and rows
564cdf0e10cSrcweir     sal_Int32 nMaxYPos = 0;
565cdf0e10cSrcweir     sal_Int32 nRow = 0;
566cdf0e10cSrcweir     sal_Int32 nColumn = 0;
567cdf0e10cSrcweir     for( nColumn = 0; nColumn < nNumberOfColumns; ++nColumn )
568cdf0e10cSrcweir     {
569cdf0e10cSrcweir         nCurrentYPos = nYPadding;
570cdf0e10cSrcweir         for( nRow = 0; nRow < nNumberOfRows; ++nRow )
571cdf0e10cSrcweir         {
572cdf0e10cSrcweir             sal_Int32 nEntry = (nColumn + nRow * nNumberOfColumns);
573cdf0e10cSrcweir             if( nEntry >= nNumberOfEntries )
574cdf0e10cSrcweir                 break;
575cdf0e10cSrcweir 
576cdf0e10cSrcweir             // text shape
577cdf0e10cSrcweir             Reference< drawing::XShape > xTextShape( aTextShapes[nEntry] );
578cdf0e10cSrcweir             if( xTextShape.is() )
579cdf0e10cSrcweir             {
580cdf0e10cSrcweir                 awt::Size aTextSize( xTextShape->getSize() );
581cdf0e10cSrcweir                 sal_Int32 nTextXPos = nCurrentXPos + nSymbolPlusDistanceWidth;
582cdf0e10cSrcweir                 if( !bSymbolsLeftSide )
583cdf0e10cSrcweir                     nTextXPos = nCurrentXPos - nSymbolPlusDistanceWidth - aTextSize.Width;
584cdf0e10cSrcweir                 xTextShape->setPosition( awt::Point( nTextXPos, nCurrentYPos ));
585cdf0e10cSrcweir             }
586cdf0e10cSrcweir 
587cdf0e10cSrcweir             // symbol
588cdf0e10cSrcweir             Reference< drawing::XShape > xSymbol( rEntries[ nEntry ].aSymbol );
589cdf0e10cSrcweir             if( xSymbol.is() )
590cdf0e10cSrcweir             {
591cdf0e10cSrcweir                 awt::Size aSymbolSize( rMaxSymbolExtent );
592cdf0e10cSrcweir                 sal_Int32 nSymbolXPos = nCurrentXPos;
593cdf0e10cSrcweir                 if( !bSymbolsLeftSide )
594cdf0e10cSrcweir                     nSymbolXPos = nCurrentXPos - rMaxSymbolExtent.Width;
595cdf0e10cSrcweir                 sal_Int32 nSymbolYPos = nCurrentYPos + ( ( nTextLineHeight - aSymbolSize.Height ) / 2 );
596cdf0e10cSrcweir                 xSymbol->setPosition( awt::Point( nSymbolXPos, nSymbolYPos ) );
597cdf0e10cSrcweir             }
598cdf0e10cSrcweir 
599cdf0e10cSrcweir             nCurrentYPos += aRowHeights[ nRow ];
600cdf0e10cSrcweir             if( nRow+1 < nNumberOfRows )
601cdf0e10cSrcweir                 nCurrentYPos += nYOffset;
602cdf0e10cSrcweir             nMaxYPos = ::std::max( nMaxYPos, nCurrentYPos );
603cdf0e10cSrcweir         }
604cdf0e10cSrcweir         if( bSymbolsLeftSide )
605cdf0e10cSrcweir         {
606cdf0e10cSrcweir             nCurrentXPos += aColumnWidths[nColumn];
607cdf0e10cSrcweir             if( nColumn+1 < nNumberOfColumns )
608cdf0e10cSrcweir                 nCurrentXPos += nXOffset;
609cdf0e10cSrcweir         }
610cdf0e10cSrcweir         else
611cdf0e10cSrcweir         {
612cdf0e10cSrcweir             nCurrentXPos -= aColumnWidths[nColumn];
613cdf0e10cSrcweir             if( nColumn+1 < nNumberOfColumns )
614cdf0e10cSrcweir                 nCurrentXPos -= nXOffset;
615cdf0e10cSrcweir         }
616cdf0e10cSrcweir     }
617cdf0e10cSrcweir 
618cdf0e10cSrcweir     if( !bIsCustomSize )
619cdf0e10cSrcweir     {
620cdf0e10cSrcweir         if( bSymbolsLeftSide )
621cdf0e10cSrcweir             aResultingLegendSize.Width  = nCurrentXPos + nXPadding;
622cdf0e10cSrcweir         else
623cdf0e10cSrcweir         {
624cdf0e10cSrcweir             sal_Int32 nLegendWidth = -(nCurrentXPos-nXPadding);
625cdf0e10cSrcweir             aResultingLegendSize.Width  = nLegendWidth;
626cdf0e10cSrcweir         }
627cdf0e10cSrcweir         aResultingLegendSize.Height = nMaxYPos + nYPadding;
628cdf0e10cSrcweir     }
629cdf0e10cSrcweir 
630cdf0e10cSrcweir     if( !bSymbolsLeftSide )
631cdf0e10cSrcweir     {
632cdf0e10cSrcweir         sal_Int32 nLegendWidth = aResultingLegendSize.Width;
633cdf0e10cSrcweir         awt::Point aPos(0,0);
634cdf0e10cSrcweir         for( sal_Int32 nEntry=0; nEntry<nNumberOfEntries; nEntry++ )
635cdf0e10cSrcweir         {
636cdf0e10cSrcweir             Reference< drawing::XShape > xSymbol( rEntries[ nEntry ].aSymbol );
637cdf0e10cSrcweir             aPos = xSymbol->getPosition();
638cdf0e10cSrcweir             aPos.X += nLegendWidth;
639cdf0e10cSrcweir             xSymbol->setPosition( aPos );
640cdf0e10cSrcweir             Reference< drawing::XShape > xText( aTextShapes[ nEntry ] );
641cdf0e10cSrcweir             aPos = xText->getPosition();
642cdf0e10cSrcweir             aPos.X += nLegendWidth;
643cdf0e10cSrcweir             xText->setPosition( aPos );
644cdf0e10cSrcweir         }
645cdf0e10cSrcweir     }
646cdf0e10cSrcweir 
647cdf0e10cSrcweir     return aResultingLegendSize;
648cdf0e10cSrcweir }
649cdf0e10cSrcweir 
650cdf0e10cSrcweir // #i109336# Improve auto positioning in chart
lcl_getLegendLeftRightMargin()651cdf0e10cSrcweir sal_Int32 lcl_getLegendLeftRightMargin()
652cdf0e10cSrcweir {
653cdf0e10cSrcweir     return 210;  // 1/100 mm
654cdf0e10cSrcweir }
655cdf0e10cSrcweir 
656cdf0e10cSrcweir // #i109336# Improve auto positioning in chart
lcl_getLegendTopBottomMargin()657cdf0e10cSrcweir sal_Int32 lcl_getLegendTopBottomMargin()
658cdf0e10cSrcweir {
659cdf0e10cSrcweir     return 185;  // 1/100 mm
660cdf0e10cSrcweir }
661cdf0e10cSrcweir 
lcl_getDefaultPosition(LegendPosition ePos,const awt::Rectangle & rOutAvailableSpace,const awt::Size & rPageSize)662cdf0e10cSrcweir chart2::RelativePosition lcl_getDefaultPosition( LegendPosition ePos, const awt::Rectangle& rOutAvailableSpace, const awt::Size & rPageSize )
663cdf0e10cSrcweir {
664cdf0e10cSrcweir     chart2::RelativePosition aResult;
665cdf0e10cSrcweir 
666cdf0e10cSrcweir     switch( ePos )
667cdf0e10cSrcweir     {
668cdf0e10cSrcweir         case LegendPosition_LINE_START:
669cdf0e10cSrcweir             {
670cdf0e10cSrcweir                 // #i109336# Improve auto positioning in chart
671cdf0e10cSrcweir                 const double fDefaultDistance = ( static_cast< double >( lcl_getLegendLeftRightMargin() ) /
672cdf0e10cSrcweir                     static_cast< double >( rPageSize.Width ) );
673cdf0e10cSrcweir                 aResult = chart2::RelativePosition(
674cdf0e10cSrcweir                     fDefaultDistance, 0.5, drawing::Alignment_LEFT );
675cdf0e10cSrcweir             }
676cdf0e10cSrcweir             break;
677cdf0e10cSrcweir         case LegendPosition_LINE_END:
678cdf0e10cSrcweir             {
679cdf0e10cSrcweir                 // #i109336# Improve auto positioning in chart
680cdf0e10cSrcweir                 const double fDefaultDistance = ( static_cast< double >( lcl_getLegendLeftRightMargin() ) /
681cdf0e10cSrcweir                     static_cast< double >( rPageSize.Width ) );
682cdf0e10cSrcweir                 aResult = chart2::RelativePosition(
683cdf0e10cSrcweir                     1.0 - fDefaultDistance, 0.5, drawing::Alignment_RIGHT );
684cdf0e10cSrcweir             }
685cdf0e10cSrcweir             break;
686cdf0e10cSrcweir         case LegendPosition_PAGE_START:
687cdf0e10cSrcweir             {
688cdf0e10cSrcweir                 // #i109336# Improve auto positioning in chart
689cdf0e10cSrcweir                 const double fDefaultDistance = ( static_cast< double >( lcl_getLegendTopBottomMargin() ) /
690cdf0e10cSrcweir                     static_cast< double >( rPageSize.Height ) );
691cdf0e10cSrcweir                 double fDistance = (static_cast<double>(rOutAvailableSpace.Y)/static_cast<double>(rPageSize.Height)) + fDefaultDistance;
692cdf0e10cSrcweir                 aResult = chart2::RelativePosition(
693cdf0e10cSrcweir                     0.5, fDistance, drawing::Alignment_TOP );
694cdf0e10cSrcweir             }
695cdf0e10cSrcweir             break;
696cdf0e10cSrcweir         case LegendPosition_PAGE_END:
697cdf0e10cSrcweir             {
698cdf0e10cSrcweir                 // #i109336# Improve auto positioning in chart
699cdf0e10cSrcweir                 const double fDefaultDistance = ( static_cast< double >( lcl_getLegendTopBottomMargin() ) /
700cdf0e10cSrcweir                     static_cast< double >( rPageSize.Height ) );
701cdf0e10cSrcweir                 aResult = chart2::RelativePosition(
702cdf0e10cSrcweir                     0.5, 1.0 - fDefaultDistance, drawing::Alignment_BOTTOM );
703cdf0e10cSrcweir             }
704cdf0e10cSrcweir             break;
705cdf0e10cSrcweir 
706cdf0e10cSrcweir         case LegendPosition_CUSTOM:
707cdf0e10cSrcweir             // to avoid warning
708cdf0e10cSrcweir         case LegendPosition_MAKE_FIXED_SIZE:
709cdf0e10cSrcweir             // nothing to be set
710cdf0e10cSrcweir             break;
711cdf0e10cSrcweir     }
712cdf0e10cSrcweir 
713cdf0e10cSrcweir     return aResult;
714cdf0e10cSrcweir }
715cdf0e10cSrcweir 
716cdf0e10cSrcweir /**  @return
717cdf0e10cSrcweir          a point relative to the upper left corner that can be used for
718cdf0e10cSrcweir          XShape::setPosition()
719cdf0e10cSrcweir */
lcl_calculatePositionAndRemainingSpace(awt::Rectangle & rRemainingSpace,const awt::Size & rPageSize,chart2::RelativePosition aRelPos,LegendPosition ePos,const awt::Size & aLegendSize)720cdf0e10cSrcweir awt::Point lcl_calculatePositionAndRemainingSpace(
721cdf0e10cSrcweir     awt::Rectangle & rRemainingSpace,
722cdf0e10cSrcweir     const awt::Size & rPageSize,
723cdf0e10cSrcweir     chart2::RelativePosition aRelPos,
724cdf0e10cSrcweir     LegendPosition ePos,
725cdf0e10cSrcweir     const awt::Size& aLegendSize )
726cdf0e10cSrcweir {
727cdf0e10cSrcweir     // calculate position
728cdf0e10cSrcweir     awt::Point aResult(
729cdf0e10cSrcweir         static_cast< sal_Int32 >( aRelPos.Primary * rPageSize.Width ),
730cdf0e10cSrcweir         static_cast< sal_Int32 >( aRelPos.Secondary * rPageSize.Height ));
731cdf0e10cSrcweir 
732cdf0e10cSrcweir     aResult = RelativePositionHelper::getUpperLeftCornerOfAnchoredObject(
733cdf0e10cSrcweir         aResult, aLegendSize, aRelPos.Anchor );
734cdf0e10cSrcweir 
735cdf0e10cSrcweir     // adapt rRemainingSpace if LegendPosition is not CUSTOM
736cdf0e10cSrcweir     // #i109336# Improve auto positioning in chart
737cdf0e10cSrcweir     sal_Int32 nXDistance = lcl_getLegendLeftRightMargin();
738cdf0e10cSrcweir     sal_Int32 nYDistance = lcl_getLegendTopBottomMargin();
739cdf0e10cSrcweir     switch( ePos )
740cdf0e10cSrcweir     {
741cdf0e10cSrcweir         case LegendPosition_LINE_START:
742cdf0e10cSrcweir             {
743cdf0e10cSrcweir                 sal_Int32 nExtent = aLegendSize.Width;
744cdf0e10cSrcweir                 rRemainingSpace.Width -= ( nExtent + nXDistance );
745cdf0e10cSrcweir                 rRemainingSpace.X += ( nExtent + nXDistance );
746cdf0e10cSrcweir             }
747cdf0e10cSrcweir         break;
748cdf0e10cSrcweir         case LegendPosition_LINE_END:
749cdf0e10cSrcweir             {
750cdf0e10cSrcweir                 rRemainingSpace.Width -= ( aLegendSize.Width + nXDistance );
751cdf0e10cSrcweir             }
752cdf0e10cSrcweir             break;
753cdf0e10cSrcweir         case LegendPosition_PAGE_START:
754cdf0e10cSrcweir             {
755cdf0e10cSrcweir                 sal_Int32 nExtent = aLegendSize.Height;
756cdf0e10cSrcweir                 rRemainingSpace.Height -= ( nExtent + nYDistance );
757cdf0e10cSrcweir                 rRemainingSpace.Y += ( nExtent + nYDistance );
758cdf0e10cSrcweir             }
759cdf0e10cSrcweir         break;
760cdf0e10cSrcweir         case LegendPosition_PAGE_END:
761cdf0e10cSrcweir             {
762cdf0e10cSrcweir                 rRemainingSpace.Height -= ( aLegendSize.Height + nYDistance );
763cdf0e10cSrcweir             }
764cdf0e10cSrcweir             break;
765cdf0e10cSrcweir 
766cdf0e10cSrcweir         default:
767cdf0e10cSrcweir             // nothing
768cdf0e10cSrcweir             break;
769cdf0e10cSrcweir     }
770cdf0e10cSrcweir 
771cdf0e10cSrcweir     // adjust the legend position. Esp. for old files that had slightly smaller legends
772cdf0e10cSrcweir     const sal_Int32 nEdgeDistance( 30 );
773cdf0e10cSrcweir     if( aResult.X + aLegendSize.Width > rPageSize.Width )
774cdf0e10cSrcweir     {
775cdf0e10cSrcweir         sal_Int32 nNewX( (rPageSize.Width - aLegendSize.Width) - nEdgeDistance );
776cdf0e10cSrcweir         if( nNewX > rPageSize.Width / 4 )
777cdf0e10cSrcweir             aResult.X = nNewX;
778cdf0e10cSrcweir     }
779cdf0e10cSrcweir     if( aResult.Y + aLegendSize.Height > rPageSize.Height )
780cdf0e10cSrcweir     {
781cdf0e10cSrcweir         sal_Int32 nNewY( (rPageSize.Height - aLegendSize.Height) - nEdgeDistance );
782cdf0e10cSrcweir         if( nNewY > rPageSize.Height / 4 )
783cdf0e10cSrcweir             aResult.Y = nNewY;
784cdf0e10cSrcweir     }
785cdf0e10cSrcweir 
786cdf0e10cSrcweir     return aResult;
787cdf0e10cSrcweir }
788cdf0e10cSrcweir 
lcl_shouldSymbolsBePlacedOnTheLeftSide(const Reference<beans::XPropertySet> & xLegendProp,sal_Int16 nDefaultWritingMode)789cdf0e10cSrcweir bool lcl_shouldSymbolsBePlacedOnTheLeftSide( const Reference< beans::XPropertySet >& xLegendProp, sal_Int16 nDefaultWritingMode )
790cdf0e10cSrcweir {
791cdf0e10cSrcweir     bool bSymbolsLeftSide = true;
792cdf0e10cSrcweir     try
793cdf0e10cSrcweir     {
794cdf0e10cSrcweir         if( SvtLanguageOptions().IsCTLFontEnabled() )
795cdf0e10cSrcweir         {
796cdf0e10cSrcweir             if(xLegendProp.is())
797cdf0e10cSrcweir             {
798cdf0e10cSrcweir                 sal_Int16 nWritingMode=-1;
799cdf0e10cSrcweir                 if( (xLegendProp->getPropertyValue( C2U("WritingMode") ) >>= nWritingMode) )
800cdf0e10cSrcweir                 {
801cdf0e10cSrcweir                     if( nWritingMode == text::WritingMode2::PAGE )
802cdf0e10cSrcweir                         nWritingMode = nDefaultWritingMode;
803cdf0e10cSrcweir                     if( nWritingMode == text::WritingMode2::RL_TB )
804cdf0e10cSrcweir                         bSymbolsLeftSide=false;
805cdf0e10cSrcweir                 }
806cdf0e10cSrcweir             }
807cdf0e10cSrcweir         }
808cdf0e10cSrcweir     }
809cdf0e10cSrcweir     catch( uno::Exception & ex )
810cdf0e10cSrcweir     {
811cdf0e10cSrcweir         ASSERT_EXCEPTION( ex );
812cdf0e10cSrcweir     }
813cdf0e10cSrcweir     return bSymbolsLeftSide;
814cdf0e10cSrcweir }
815cdf0e10cSrcweir 
816cdf0e10cSrcweir } // anonymous namespace
817cdf0e10cSrcweir 
VLegend(const Reference<XLegend> & xLegend,const Reference<uno::XComponentContext> & xContext,const std::vector<LegendEntryProvider * > & rLegendEntryProviderList)818cdf0e10cSrcweir VLegend::VLegend(
819cdf0e10cSrcweir     const Reference< XLegend > & xLegend,
820cdf0e10cSrcweir     const Reference< uno::XComponentContext > & xContext,
821cdf0e10cSrcweir     const std::vector< LegendEntryProvider* >& rLegendEntryProviderList ) :
822cdf0e10cSrcweir         m_xLegend( xLegend ),
823cdf0e10cSrcweir         m_xContext( xContext ),
824cdf0e10cSrcweir         m_aLegendEntryProviderList( rLegendEntryProviderList )
825cdf0e10cSrcweir {
826cdf0e10cSrcweir }
827cdf0e10cSrcweir 
828cdf0e10cSrcweir // ----------------------------------------
829cdf0e10cSrcweir 
init(const Reference<drawing::XShapes> & xTargetPage,const Reference<lang::XMultiServiceFactory> & xFactory,const Reference<frame::XModel> & xModel)830cdf0e10cSrcweir void VLegend::init(
831cdf0e10cSrcweir     const Reference< drawing::XShapes >& xTargetPage,
832cdf0e10cSrcweir     const Reference< lang::XMultiServiceFactory >& xFactory,
833cdf0e10cSrcweir     const Reference< frame::XModel >& xModel )
834cdf0e10cSrcweir {
835cdf0e10cSrcweir     m_xTarget = xTargetPage;
836cdf0e10cSrcweir     m_xShapeFactory = xFactory;
837cdf0e10cSrcweir     m_xModel = xModel;
838cdf0e10cSrcweir }
839cdf0e10cSrcweir 
840cdf0e10cSrcweir // ----------------------------------------
841cdf0e10cSrcweir 
setDefaultWritingMode(sal_Int16 nDefaultWritingMode)842cdf0e10cSrcweir void VLegend::setDefaultWritingMode( sal_Int16 nDefaultWritingMode )
843cdf0e10cSrcweir {
844cdf0e10cSrcweir     m_nDefaultWritingMode = nDefaultWritingMode;
845cdf0e10cSrcweir }
846cdf0e10cSrcweir 
847cdf0e10cSrcweir // ----------------------------------------
848cdf0e10cSrcweir 
isVisible(const Reference<XLegend> & xLegend)849cdf0e10cSrcweir bool VLegend::isVisible( const Reference< XLegend > & xLegend )
850cdf0e10cSrcweir {
851cdf0e10cSrcweir     if( ! xLegend.is())
852cdf0e10cSrcweir         return sal_False;
853cdf0e10cSrcweir 
854cdf0e10cSrcweir     sal_Bool bShow = sal_False;
855cdf0e10cSrcweir     try
856cdf0e10cSrcweir     {
857cdf0e10cSrcweir         Reference< beans::XPropertySet > xLegendProp( xLegend, uno::UNO_QUERY_THROW );
858cdf0e10cSrcweir         xLegendProp->getPropertyValue( C2U( "Show" )) >>= bShow;
859cdf0e10cSrcweir     }
860cdf0e10cSrcweir     catch( uno::Exception & ex )
861cdf0e10cSrcweir     {
862cdf0e10cSrcweir         ASSERT_EXCEPTION( ex );
863cdf0e10cSrcweir     }
864cdf0e10cSrcweir 
865cdf0e10cSrcweir     return bShow;
866cdf0e10cSrcweir }
867cdf0e10cSrcweir 
868cdf0e10cSrcweir // ----------------------------------------
869cdf0e10cSrcweir 
createShapes(const awt::Size & rAvailableSpace,const awt::Size & rPageSize)870cdf0e10cSrcweir void VLegend::createShapes(
871cdf0e10cSrcweir     const awt::Size & rAvailableSpace,
872cdf0e10cSrcweir     const awt::Size & rPageSize )
873cdf0e10cSrcweir {
874cdf0e10cSrcweir     if(! (m_xLegend.is() &&
875cdf0e10cSrcweir           m_xShapeFactory.is() &&
876cdf0e10cSrcweir           m_xTarget.is()))
877cdf0e10cSrcweir         return;
878cdf0e10cSrcweir 
879cdf0e10cSrcweir     try
880cdf0e10cSrcweir     {
881cdf0e10cSrcweir         //create shape and add to page
882cdf0e10cSrcweir         m_xShape.set( m_xShapeFactory->createInstance(
883cdf0e10cSrcweir                           C2U( "com.sun.star.drawing.GroupShape" )), uno::UNO_QUERY );
884cdf0e10cSrcweir         m_xTarget->add( m_xShape );
885cdf0e10cSrcweir 
886cdf0e10cSrcweir         // set name to enable selection
887cdf0e10cSrcweir 		{
888cdf0e10cSrcweir             OUString aLegendParticle( ObjectIdentifier::createParticleForLegend( m_xLegend, m_xModel ) );
889cdf0e10cSrcweir             ShapeFactory::setShapeName( m_xShape, ObjectIdentifier::createClassifiedIdentifierForParticle( aLegendParticle ) );
890cdf0e10cSrcweir         }
891cdf0e10cSrcweir 
892cdf0e10cSrcweir         // create and insert sub-shapes
893cdf0e10cSrcweir         Reference< drawing::XShapes > xLegendContainer( m_xShape, uno::UNO_QUERY );
894cdf0e10cSrcweir         if( xLegendContainer.is())
895cdf0e10cSrcweir         {
896cdf0e10cSrcweir             Reference< drawing::XShape > xBorder(
897cdf0e10cSrcweir                 m_xShapeFactory->createInstance(
898cdf0e10cSrcweir                     C2U( "com.sun.star.drawing.RectangleShape" )), uno::UNO_QUERY );
899cdf0e10cSrcweir 
900cdf0e10cSrcweir             // for quickly setting properties
901cdf0e10cSrcweir             tPropertyValues aLineFillProperties;
902cdf0e10cSrcweir             tPropertyValues aTextProperties;
903cdf0e10cSrcweir 
904cdf0e10cSrcweir             Reference< beans::XPropertySet > xLegendProp( m_xLegend, uno::UNO_QUERY );
905cdf0e10cSrcweir             ::com::sun::star::chart::ChartLegendExpansion eExpansion = ::com::sun::star::chart::ChartLegendExpansion_HIGH;
906cdf0e10cSrcweir             awt::Size aLegendSize( rAvailableSpace );
907cdf0e10cSrcweir 
908cdf0e10cSrcweir             if( xLegendProp.is())
909cdf0e10cSrcweir             {
910cdf0e10cSrcweir                 // get Expansion property
911cdf0e10cSrcweir                 xLegendProp->getPropertyValue( C2U( "Expansion" )) >>= eExpansion;
912cdf0e10cSrcweir                 if( eExpansion == ::com::sun::star::chart::ChartLegendExpansion_CUSTOM )
913cdf0e10cSrcweir                 {
914cdf0e10cSrcweir                     RelativeSize aRelativeSize;
915cdf0e10cSrcweir                     if ((xLegendProp->getPropertyValue( C2U( "RelativeSize" )) >>= aRelativeSize))
916cdf0e10cSrcweir                     {
917cdf0e10cSrcweir                         aLegendSize.Width = static_cast<sal_Int32>( ::rtl::math::approxCeil( aRelativeSize.Primary * rPageSize.Width ) ); //i117185
918cdf0e10cSrcweir                         aLegendSize.Height = static_cast<sal_Int32>( ::rtl::math::approxCeil( aRelativeSize.Secondary * rPageSize.Height ) ); //i117185
919cdf0e10cSrcweir                     }
920cdf0e10cSrcweir                     else
921cdf0e10cSrcweir                         eExpansion = ::com::sun::star::chart::ChartLegendExpansion_HIGH;
922cdf0e10cSrcweir                 }
923cdf0e10cSrcweir                 lcl_getProperties( xLegendProp, aLineFillProperties, aTextProperties, rPageSize );
924cdf0e10cSrcweir             }
925cdf0e10cSrcweir 
926cdf0e10cSrcweir             if( xBorder.is())
927cdf0e10cSrcweir             {
928cdf0e10cSrcweir                 xLegendContainer->add( xBorder );
929cdf0e10cSrcweir 
930cdf0e10cSrcweir                 // apply legend properties
931cdf0e10cSrcweir                 PropertyMapper::setMultiProperties(
932cdf0e10cSrcweir                     aLineFillProperties.first, aLineFillProperties.second,
933cdf0e10cSrcweir                     Reference< beans::XPropertySet >( xBorder, uno::UNO_QUERY ));
934cdf0e10cSrcweir 
935cdf0e10cSrcweir                 //because of this name this border will be used for marking the legend
936cdf0e10cSrcweir                 ShapeFactory(m_xShapeFactory).setShapeName( xBorder, C2U("MarkHandles") );
937cdf0e10cSrcweir             }
938cdf0e10cSrcweir 
939cdf0e10cSrcweir             // create entries
940cdf0e10cSrcweir             double fViewFontSize = lcl_CalcViewFontSize( xLegendProp, rPageSize );//todo
941cdf0e10cSrcweir             // #i109336# Improve auto positioning in chart
942cdf0e10cSrcweir             sal_Int32 nSymbolHeigth = static_cast< sal_Int32 >( fViewFontSize * 0.6  );
943cdf0e10cSrcweir             sal_Int32 nSymbolWidth = static_cast< sal_Int32 >( nSymbolHeigth );
944cdf0e10cSrcweir 
945cdf0e10cSrcweir             ::std::vector< LegendEntryProvider* >::const_iterator       aIter = m_aLegendEntryProviderList.begin();
946cdf0e10cSrcweir             const ::std::vector< LegendEntryProvider* >::const_iterator aEnd  = m_aLegendEntryProviderList.end();
947cdf0e10cSrcweir             for( aIter = m_aLegendEntryProviderList.begin(); aIter != aEnd; aIter++ )
948cdf0e10cSrcweir             {
949cdf0e10cSrcweir                 LegendEntryProvider* pLegendEntryProvider( *aIter );
950cdf0e10cSrcweir                 if( pLegendEntryProvider )
951cdf0e10cSrcweir                 {
952cdf0e10cSrcweir                     awt::Size aCurrentRatio = pLegendEntryProvider->getPreferredLegendKeyAspectRatio();
953cdf0e10cSrcweir                     sal_Int32 nCurrentWidth = aCurrentRatio.Width;
954cdf0e10cSrcweir                     if( aCurrentRatio.Height > 0 )
955cdf0e10cSrcweir                     {
956cdf0e10cSrcweir                         nCurrentWidth = nSymbolHeigth* aCurrentRatio.Width/aCurrentRatio.Height;
957cdf0e10cSrcweir                     }
958cdf0e10cSrcweir                     nSymbolWidth = std::max( nSymbolWidth, nCurrentWidth );
959cdf0e10cSrcweir                 }
960cdf0e10cSrcweir             }
961cdf0e10cSrcweir             awt::Size aMaxSymbolExtent( nSymbolWidth, nSymbolHeigth );
962cdf0e10cSrcweir 
963cdf0e10cSrcweir             tViewLegendEntryContainer aViewEntries;
964cdf0e10cSrcweir             for( aIter = m_aLegendEntryProviderList.begin(); aIter != aEnd; aIter++ )
965cdf0e10cSrcweir             {
966cdf0e10cSrcweir                 LegendEntryProvider* pLegendEntryProvider( *aIter );
967cdf0e10cSrcweir                 if( pLegendEntryProvider )
968cdf0e10cSrcweir                 {
969cdf0e10cSrcweir                     std::vector< ViewLegendEntry > aNewEntries = pLegendEntryProvider->createLegendEntries( aMaxSymbolExtent, eExpansion, xLegendProp, xLegendContainer, m_xShapeFactory, m_xContext );
970cdf0e10cSrcweir                     aViewEntries.insert( aViewEntries.end(), aNewEntries.begin(), aNewEntries.end() );
971cdf0e10cSrcweir                 }
972cdf0e10cSrcweir             }
973cdf0e10cSrcweir 
974cdf0e10cSrcweir             bool bSymbolsLeftSide = lcl_shouldSymbolsBePlacedOnTheLeftSide( xLegendProp, m_nDefaultWritingMode );
975cdf0e10cSrcweir 
976cdf0e10cSrcweir             // place entries
977cdf0e10cSrcweir             aLegendSize = lcl_placeLegendEntries( aViewEntries, eExpansion, bSymbolsLeftSide, fViewFontSize, aMaxSymbolExtent
978cdf0e10cSrcweir                 , aTextProperties, xLegendContainer, m_xShapeFactory, aLegendSize );
979cdf0e10cSrcweir 
980cdf0e10cSrcweir             if( xBorder.is() )
981cdf0e10cSrcweir                 xBorder->setSize( aLegendSize );
982cdf0e10cSrcweir         }
983cdf0e10cSrcweir     }
984cdf0e10cSrcweir     catch( uno::Exception & ex )
985cdf0e10cSrcweir     {
986cdf0e10cSrcweir         ASSERT_EXCEPTION( ex );
987cdf0e10cSrcweir     }
988cdf0e10cSrcweir }
989cdf0e10cSrcweir 
990cdf0e10cSrcweir // ----------------------------------------
991cdf0e10cSrcweir 
changePosition(awt::Rectangle & rOutAvailableSpace,const awt::Size & rPageSize)992cdf0e10cSrcweir void VLegend::changePosition(
993cdf0e10cSrcweir     awt::Rectangle & rOutAvailableSpace,
994cdf0e10cSrcweir     const awt::Size & rPageSize )
995cdf0e10cSrcweir {
996cdf0e10cSrcweir     if(! m_xShape.is())
997cdf0e10cSrcweir         return;
998cdf0e10cSrcweir 
999cdf0e10cSrcweir     try
1000cdf0e10cSrcweir     {
1001cdf0e10cSrcweir         // determine position and alignment depending on default position
1002cdf0e10cSrcweir         awt::Size aLegendSize = m_xShape->getSize();
1003cdf0e10cSrcweir         Reference< beans::XPropertySet > xLegendProp( m_xLegend, uno::UNO_QUERY_THROW );
1004cdf0e10cSrcweir         chart2::RelativePosition aRelativePosition;
1005cdf0e10cSrcweir 
1006cdf0e10cSrcweir         bool bAutoPosition =
1007cdf0e10cSrcweir             ! (xLegendProp->getPropertyValue( C2U( "RelativePosition" )) >>= aRelativePosition);
1008cdf0e10cSrcweir 
1009cdf0e10cSrcweir         LegendPosition ePos = LegendPosition_CUSTOM;
1010cdf0e10cSrcweir         xLegendProp->getPropertyValue( C2U( "AnchorPosition" )) >>= ePos;
1011cdf0e10cSrcweir 
1012cdf0e10cSrcweir         //calculate position
1013cdf0e10cSrcweir         if( bAutoPosition )
1014cdf0e10cSrcweir         {
1015cdf0e10cSrcweir             // auto position: relative to remaining space
1016cdf0e10cSrcweir             aRelativePosition = lcl_getDefaultPosition( ePos, rOutAvailableSpace, rPageSize );
1017cdf0e10cSrcweir             awt::Point aPos = lcl_calculatePositionAndRemainingSpace(
1018cdf0e10cSrcweir                 rOutAvailableSpace, rPageSize, aRelativePosition, ePos, aLegendSize );
1019cdf0e10cSrcweir             m_xShape->setPosition( aPos );
1020cdf0e10cSrcweir         }
1021cdf0e10cSrcweir         else
1022cdf0e10cSrcweir         {
1023cdf0e10cSrcweir             // manual position: relative to whole page
1024cdf0e10cSrcweir             awt::Rectangle aAvailableSpace( 0, 0, rPageSize.Width, rPageSize.Height );
1025cdf0e10cSrcweir             awt::Point aPos = lcl_calculatePositionAndRemainingSpace(
1026cdf0e10cSrcweir                 aAvailableSpace, rPageSize, aRelativePosition, ePos, aLegendSize );
1027cdf0e10cSrcweir             m_xShape->setPosition( aPos );
1028cdf0e10cSrcweir 
1029cdf0e10cSrcweir             if( ePos != LegendPosition_CUSTOM )
1030cdf0e10cSrcweir             {
1031cdf0e10cSrcweir                 // calculate remaining space as if having autoposition:
1032cdf0e10cSrcweir                 aRelativePosition = lcl_getDefaultPosition( ePos, rOutAvailableSpace, rPageSize );
1033cdf0e10cSrcweir                 lcl_calculatePositionAndRemainingSpace(
1034cdf0e10cSrcweir                     rOutAvailableSpace, rPageSize, aRelativePosition, ePos, aLegendSize );
1035cdf0e10cSrcweir             }
1036cdf0e10cSrcweir         }
1037cdf0e10cSrcweir     }
1038cdf0e10cSrcweir     catch( uno::Exception & ex )
1039cdf0e10cSrcweir     {
1040cdf0e10cSrcweir         ASSERT_EXCEPTION( ex );
1041cdf0e10cSrcweir     }
1042cdf0e10cSrcweir }
1043cdf0e10cSrcweir 
1044cdf0e10cSrcweir //.............................................................................
1045cdf0e10cSrcweir } //namespace chart
1046cdf0e10cSrcweir //.............................................................................
1047