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

Generated by: LCOV version 1.10