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