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

Generated by: LCOV version 1.11