LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/chart2/source/view/main - VLegend.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 295 459 64.3 %
Date: 2013-07-09 Functions: 20 20 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10