summaryrefslogtreecommitdiff
path: root/chart2/source/view/main
diff options
context:
space:
mode:
Diffstat (limited to 'chart2/source/view/main')
-rw-r--r--chart2/source/view/main/ChartItemPool.cxx5
-rw-r--r--chart2/source/view/main/VLegend.cxx495
-rw-r--r--chart2/source/view/main/VLegendSymbolFactory.cxx288
3 files changed, 425 insertions, 363 deletions
diff --git a/chart2/source/view/main/ChartItemPool.cxx b/chart2/source/view/main/ChartItemPool.cxx
index 60e880ab311e..c66044b9aa0d 100644
--- a/chart2/source/view/main/ChartItemPool.cxx
+++ b/chart2/source/view/main/ChartItemPool.cxx
@@ -44,6 +44,8 @@
#include <editeng/editids.hrc>
#include <svx/svxids.hrc>
+#include <com/sun/star/chart2/LegendPosition.hpp>
+
namespace chart
{
@@ -69,7 +71,8 @@ ChartItemPool::ChartItemPool():
ppPoolDefaults[SCHATTR_PERCENT_NUMBERFORMAT_SOURCE - SCHATTR_START] = new SfxBoolItem(SCHATTR_PERCENT_NUMBERFORMAT_SOURCE);
//legend
- ppPoolDefaults[SCHATTR_LEGEND_POS - SCHATTR_START] = new SvxChartLegendPosItem( CHLEGEND_RIGHT, SCHATTR_LEGEND_POS );
+ ppPoolDefaults[SCHATTR_LEGEND_POS - SCHATTR_START] = new SfxInt32Item(SCHATTR_LEGEND_POS, ::com::sun::star::chart2::LegendPosition_LINE_END );
+ ppPoolDefaults[SCHATTR_LEGEND_SHOW - SCHATTR_START] = new SfxBoolItem(SCHATTR_LEGEND_SHOW, sal_True);
//text
ppPoolDefaults[SCHATTR_TEXT_DEGREES - SCHATTR_START] = new SfxInt32Item(SCHATTR_TEXT_DEGREES, 0);
diff --git a/chart2/source/view/main/VLegend.cxx b/chart2/source/view/main/VLegend.cxx
index fbc74bad05a5..33e1d1f26aa4 100644
--- a/chart2/source/view/main/VLegend.cxx
+++ b/chart2/source/view/main/VLegend.cxx
@@ -36,13 +36,14 @@
#include "ShapeFactory.hxx"
#include "RelativeSizeHelper.hxx"
#include "LegendEntryProvider.hxx"
+#include "chartview/DrawModelWrapper.hxx"
#include <com/sun/star/text/XTextRange.hpp>
#include <com/sun/star/text/WritingMode2.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/XPropertyState.hpp>
#include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
#include <com/sun/star/drawing/LineJoint.hpp>
-#include <com/sun/star/chart2/LegendExpansion.hpp>
+#include <com/sun/star/chart/ChartLegendExpansion.hpp>
#include <com/sun/star/chart2/LegendPosition.hpp>
#include <com/sun/star/chart2/RelativePosition.hpp>
#include <rtl/ustrbuf.hxx>
@@ -123,7 +124,6 @@ void lcl_getProperties(
const Reference< beans::XPropertySet > & xLegendProp,
tPropertyValues & rOutLineFillProperties,
tPropertyValues & rOutTextProperties,
- sal_Int32 nMaxLabelWidth,
const awt::Size & rReferenceSize )
{
// Get Line- and FillProperties from model legend
@@ -146,7 +146,7 @@ void lcl_getProperties(
aTextValueMap[ C2U("TextAutoGrowHeight") ] = uno::makeAny( sal_True );
aTextValueMap[ C2U("TextAutoGrowWidth") ] = uno::makeAny( sal_True );
aTextValueMap[ C2U("TextHorizontalAdjust") ] = uno::makeAny( eHorizAdjust );
- aTextValueMap[ C2U("TextMaximumFrameWidth") ] = uno::makeAny( nMaxLabelWidth );
+ aTextValueMap[ C2U("TextMaximumFrameWidth") ] = uno::makeAny( rReferenceSize.Width ); //needs to be overwritten by actual available space in the legend
// recalculate font size
awt::Size aPropRefSize;
@@ -193,16 +193,10 @@ awt::Size lcl_createTextShapes(
try
{
// create label shape
- Reference< drawing::XShape > xGroupShapeForSingleEntry(
- xShapeFactory->createInstance(
- C2U( "com.sun.star.drawing.GroupShape" )), uno::UNO_QUERY_THROW );
- Reference< drawing::XShape >xEntry(
+ Reference< drawing::XShape > xEntry(
xShapeFactory->createInstance(
C2U( "com.sun.star.drawing.TextShape" )), uno::UNO_QUERY_THROW );
- xTarget->add( xGroupShapeForSingleEntry );
-
- Reference< drawing::XShapes > xGroup( xGroupShapeForSingleEntry, uno::UNO_QUERY_THROW );
- xGroup->add( xEntry );
+ xTarget->add( xEntry );
// set label text
Sequence< Reference< XFormattedString > > aLabelSeq = (*aIt).aLabel;
@@ -230,7 +224,7 @@ awt::Size lcl_createTextShapes(
aResult.Height = ::std::max( aResult.Height, aCurrSize.Height );
}
- rOutTextShapes.push_back( xGroupShapeForSingleEntry );
+ rOutTextShapes.push_back( xEntry );
}
catch( uno::Exception & ex )
{
@@ -241,57 +235,272 @@ awt::Size lcl_createTextShapes(
return aResult;
}
+void lcl_collectColumnWidths( std::vector< sal_Int32 >& rColumnWidths, const sal_Int32 nNumberOfRows, const sal_Int32 nNumberOfColumns
+ , const ::std::vector< Reference< drawing::XShape > > aTextShapes, sal_Int32 nSymbolPlusDistanceWidth )
+{
+ rColumnWidths.clear();
+ sal_Int32 nRow = 0;
+ sal_Int32 nColumn = 0;
+ sal_Int32 nNumberOfEntries = aTextShapes.size();
+ for( ; nRow < nNumberOfRows; ++nRow )
+ {
+ for( nColumn = 0; nColumn < nNumberOfColumns; ++nColumn )
+ {
+ sal_Int32 nEntry = (nColumn + nRow * nNumberOfColumns);
+ if( nEntry < nNumberOfEntries )
+ {
+ awt::Size aTextSize( aTextShapes[ nEntry ]->getSize() );
+ sal_Int32 nWidth = nSymbolPlusDistanceWidth + aTextSize.Width;
+ if( nRow==0 )
+ rColumnWidths.push_back( nWidth );
+ else
+ rColumnWidths[nColumn] = ::std::max( nWidth, rColumnWidths[nColumn] );
+ }
+ }
+ }
+}
-void lcl_placeLegendEntries(
- const tViewLegendEntryContainer & rEntries,
- LegendExpansion eExpansion,
+void lcl_collectRowHeighs( std::vector< sal_Int32 >& rRowHeights, const sal_Int32 nNumberOfRows, const sal_Int32 nNumberOfColumns
+ , const ::std::vector< Reference< drawing::XShape > > aTextShapes )
+{
+ // calculate maximum height for each row
+ // and collect column widths
+ rRowHeights.clear();
+ sal_Int32 nRow = 0;
+ sal_Int32 nColumn = 0;
+ sal_Int32 nNumberOfEntries = aTextShapes.size();
+ for( ; nRow < nNumberOfRows; ++nRow )
+ {
+ sal_Int32 nCurrentRowHeight = 0;
+ for( nColumn = 0; nColumn < nNumberOfColumns; ++nColumn )
+ {
+ sal_Int32 nEntry = (nColumn + nRow * nNumberOfColumns);
+ if( nEntry < nNumberOfEntries )
+ {
+ awt::Size aTextSize( aTextShapes[ nEntry ]->getSize() );
+ nCurrentRowHeight = ::std::max( nCurrentRowHeight, aTextSize.Height );
+ }
+ }
+ rRowHeights.push_back( nCurrentRowHeight );
+ }
+}
+
+sal_Int32 lcl_getTextLineHeight( const std::vector< sal_Int32 >& aRowHeights, const sal_Int32 nNumberOfRows, double fViewFontSize )
+{
+ const sal_Int32 nFontHeight = static_cast< sal_Int32 >( fViewFontSize );
+ sal_Int32 nTextLineHeight = nFontHeight;
+ for( sal_Int32 nR=0; nR<nNumberOfRows; nR++ )
+ {
+ sal_Int32 nFullTextHeight = aRowHeights[ nR ];
+ if( ( nFullTextHeight / nFontHeight ) <= 1 )
+ {
+ nTextLineHeight = nFullTextHeight;//found an entry with one line-> have real text height
+ break;
+ }
+ }
+ return nTextLineHeight;
+}
+
+//returns resulting legend size
+awt::Size lcl_placeLegendEntries(
+ tViewLegendEntryContainer & rEntries,
+ ::com::sun::star::chart::ChartLegendExpansion eExpansion,
bool bSymbolsLeftSide,
- const Reference< beans::XPropertySet > & xProperties,
+ double fViewFontSize,
+ const awt::Size& rMaxSymbolExtent,
tPropertyValues & rTextProperties,
const Reference< drawing::XShapes > & xTarget,
const Reference< lang::XMultiServiceFactory > & xShapeFactory,
- const Reference< uno::XComponentContext > & /* xContext */,
- const awt::Size & rAvailableSpace,
- const awt::Size & rPageSize,
- awt::Size & rOutLegendSize )
+ const awt::Size & rAvailableSpace )
{
- double fViewFontSize = lcl_CalcViewFontSize( xProperties, rPageSize );
+ bool bIsCustomSize = (eExpansion == ::com::sun::star::chart::ChartLegendExpansion_CUSTOM);
+ awt::Size aResultingLegendSize(0,0);
+ if( bIsCustomSize )
+ aResultingLegendSize = rAvailableSpace;
- // padding as percentage of the font height
// #i109336# Improve auto positioning in chart
- double fXPadding = 0.1;
- double fYPadding = 0.2;
- double fXOffset = 0.15;
- double fYOffset = 0.15;
-
- const sal_Int32 nXPadding = static_cast< sal_Int32 >( fViewFontSize * fXPadding );
- const sal_Int32 nYPadding = static_cast< sal_Int32 >( fViewFontSize * fYPadding );
- const sal_Int32 nXOffset = static_cast< sal_Int32 >( fViewFontSize * fXOffset );
- const sal_Int32 nYOffset = static_cast< sal_Int32 >( fViewFontSize * fYOffset );
+ sal_Int32 nXPadding = static_cast< sal_Int32 >( std::max( 100.0, fViewFontSize * 0.33 ) );
+ //sal_Int32 nXPadding = static_cast< sal_Int32 >( std::max( 200.0, fViewFontSize * 0.33 ) );
+ sal_Int32 nXOffset = static_cast< sal_Int32 >( std::max( 100.0, fViewFontSize * 0.66 ) );
+ sal_Int32 nYPadding = static_cast< sal_Int32 >( std::max( 100.0, fViewFontSize * 0.2 ) );
+ sal_Int32 nYOffset = static_cast< sal_Int32 >( std::max( 100.0, fViewFontSize * 0.2 ) );
+ //sal_Int32 nYOffset = static_cast< sal_Int32 >( std::max( 230.0, fViewFontSize * 0.45 ) );
+
+ const sal_Int32 nSymbolToTextDistance = static_cast< sal_Int32 >( std::max( 100.0, fViewFontSize * 0.22 ) );//minimum 1mm
+ const sal_Int32 nSymbolPlusDistanceWidth = rMaxSymbolExtent.Width + nSymbolToTextDistance;
+ sal_Int32 nMaxTextWidth = rAvailableSpace.Width - (2 * nXPadding) - nSymbolPlusDistanceWidth;
+ rtl::OUString aPropNameTextMaximumFrameWidth( C2U("TextMaximumFrameWidth") );
+ uno::Any* pFrameWidthAny = PropertyMapper::getValuePointer( rTextProperties.second, rTextProperties.first, aPropNameTextMaximumFrameWidth);
+ if(pFrameWidthAny)
+ {
+ if( eExpansion == ::com::sun::star::chart::ChartLegendExpansion_HIGH )
+ {
+ // limit the width of texts to 30% of the total available width
+ // #i109336# Improve auto positioning in chart
+ nMaxTextWidth = rAvailableSpace.Width * 3 / 10;
+ }
+ *pFrameWidthAny = uno::makeAny(nMaxTextWidth);
+ }
::std::vector< Reference< drawing::XShape > > aTextShapes;
- awt::Size aMaxEntryExtent = lcl_createTextShapes(
- rEntries, xShapeFactory, xTarget, aTextShapes, rTextProperties );
+ awt::Size aMaxEntryExtent = lcl_createTextShapes( rEntries, xShapeFactory, xTarget, aTextShapes, rTextProperties );
OSL_ASSERT( aTextShapes.size() == rEntries.size());
- // #i109336# Improve auto positioning in chart
- double fSymbolSizeFraction = 0.8;
- awt::Size aMaxSymbolExtent( static_cast< sal_Int32 >( fViewFontSize * fSymbolSizeFraction * 3.0 / 2.0 ),
- static_cast< sal_Int32 >( fViewFontSize * fSymbolSizeFraction ) );
-
- sal_Int32 nCurrentXPos = nXPadding;
- sal_Int32 nCurrentYPos = nYPadding;
- sal_Int32 nMaxEntryWidth = 2 * nXOffset + aMaxSymbolExtent.Width + aMaxEntryExtent.Width;
+ sal_Int32 nMaxEntryWidth = nXOffset + nSymbolPlusDistanceWidth + aMaxEntryExtent.Width;
sal_Int32 nMaxEntryHeight = nYOffset + aMaxEntryExtent.Height;
sal_Int32 nNumberOfEntries = rEntries.size();
- if( !bSymbolsLeftSide )
- nCurrentXPos = -nXPadding;
-
sal_Int32 nNumberOfColumns = 0, nNumberOfRows = 0;
+ std::vector< sal_Int32 > aColumnWidths;
+ std::vector< sal_Int32 > aRowHeights;
+
+ sal_Int32 nTextLineHeight = static_cast< sal_Int32 >( fViewFontSize );
// determine layout depending on LegendExpansion
- if( eExpansion == LegendExpansion_HIGH )
+ if( eExpansion == ::com::sun::star::chart::ChartLegendExpansion_CUSTOM )
+ {
+ sal_Int32 nCurrentRow=0;
+ sal_Int32 nCurrentColumn=-1;
+ sal_Int32 nColumnCount=0;
+ sal_Int32 nMaxColumnCount=-1;
+ for( sal_Int32 nN=0; nN<static_cast<sal_Int32>(aTextShapes.size()); nN++ )
+ {
+ Reference< drawing::XShape > xShape( aTextShapes[nN] );
+ if( !xShape.is() )
+ continue;
+ awt::Size aSize( xShape->getSize() );
+ sal_Int32 nNewWidth = aSize.Width + nSymbolPlusDistanceWidth;
+ sal_Int32 nCurrentColumnCount = aColumnWidths.size();
+
+ //are we allowed to add a new column?
+ if( nMaxColumnCount==-1 || (nCurrentColumn+1) < nMaxColumnCount )
+ {
+ //try add a new column
+ nCurrentColumn++;
+ if( nCurrentColumn < nCurrentColumnCount )
+ {
+ //check wether the current column width is sufficient for the new entry
+ if( aColumnWidths[nCurrentColumn]>=nNewWidth )
+ {
+ //all good proceed with next entry
+ continue;
+ }
+ }
+ if( nCurrentColumn < nCurrentColumnCount )
+ aColumnWidths[nCurrentColumn] = std::max( nNewWidth, aColumnWidths[nCurrentColumn] );
+ else
+ aColumnWidths.push_back(nNewWidth);
+
+ //do the columns still fit into the given size?
+ nCurrentColumnCount = aColumnWidths.size();//update count
+ sal_Int32 nSumWidth = 0;
+ for( sal_Int32 nC=0; nC<nCurrentColumnCount; nC++ )
+ nSumWidth += aColumnWidths[nC];
+
+ if( nSumWidth <= rAvailableSpace.Width || nCurrentColumnCount==1 )
+ {
+ //all good proceed with next entry
+ continue;
+ }
+ else
+ {
+ //not enough space for the current amount of columns
+ //try again with less columns
+ nMaxColumnCount = nCurrentColumnCount-1;
+ nN=-1;
+ nCurrentRow=0;
+ nCurrentColumn=-1;
+ nColumnCount=0;
+ aColumnWidths.clear();
+ }
+ }
+ else
+ {
+ //add a new row and try the same entry again
+ nCurrentRow++;
+ nCurrentColumn=-1;
+ nN--;
+ }
+ }
+ nNumberOfColumns = aColumnWidths.size();
+ nNumberOfRows = nCurrentRow+1;
+
+ //check if there is not enough space so that some entries must be removed
+ lcl_collectRowHeighs( aRowHeights, nNumberOfRows, nNumberOfColumns, aTextShapes );
+ nTextLineHeight = lcl_getTextLineHeight( aRowHeights, nNumberOfRows, fViewFontSize );
+ sal_Int32 nSumHeight = 0;
+ for( sal_Int32 nR=0; nR<nNumberOfRows; nR++ )
+ nSumHeight += aRowHeights[nR];
+ sal_Int32 nRemainingSpace = rAvailableSpace.Height - nSumHeight;
+
+ if( nRemainingSpace<0 )
+ {
+ //remove entries that are too big
+ for( sal_Int32 nR=nNumberOfRows; nR--; )
+ {
+ for( sal_Int32 nC=nNumberOfColumns; nC--; )
+ {
+ sal_Int32 nEntry = (nC + nR * nNumberOfColumns);
+ if( nEntry < static_cast<sal_Int32>(aTextShapes.size()) )
+ {
+ DrawModelWrapper::removeShape( aTextShapes[nEntry] );
+ aTextShapes.pop_back();
+ }
+ if( nEntry < nNumberOfEntries )
+ {
+ DrawModelWrapper::removeShape( rEntries[ nEntry ].aSymbol );
+ rEntries.pop_back();
+ nNumberOfEntries--;
+ }
+ }
+ nSumHeight -= aRowHeights[nR];
+ aRowHeights.pop_back();
+ nRemainingSpace = rAvailableSpace.Height - nSumHeight;
+ if( nRemainingSpace>=0 )
+ break;
+ }
+ nNumberOfRows = static_cast<sal_Int32>(aRowHeights.size());
+ }
+ if( nRemainingSpace > 0 )
+ {
+ sal_Int32 nNormalSpacingHeight = 2*nYPadding+(nNumberOfRows-1)*nYOffset;
+ if( nRemainingSpace < nNormalSpacingHeight )
+ {
+ //reduce spacing between the entries
+ nYPadding = nYOffset = nRemainingSpace/(nNumberOfRows+1);
+ }
+ else
+ {
+ //we have some space left that should be spread equally between all rows
+ sal_Int32 nRemainingSingleSpace = (nRemainingSpace-nNormalSpacingHeight)/(nNumberOfRows+1);
+ nYPadding += nRemainingSingleSpace;
+ nYOffset += nRemainingSingleSpace;
+ }
+ }
+
+ //check spacing between columns
+ sal_Int32 nSumWidth = 0;
+ for( sal_Int32 nC=0; nC<nNumberOfColumns; nC++ )
+ nSumWidth += aColumnWidths[nC];
+ nRemainingSpace = rAvailableSpace.Width - nSumWidth;
+ if( nRemainingSpace>=0 )
+ {
+ sal_Int32 nNormalSpacingWidth = 2*nXPadding+(nNumberOfColumns-1)*nXOffset;
+ if( nRemainingSpace < nNormalSpacingWidth )
+ {
+ //reduce spacing between the entries
+ nXPadding = nXOffset = nRemainingSpace/(nNumberOfColumns+1);
+ }
+ else
+ {
+ //we have some space left that should be spread equally between all columns
+ sal_Int32 nRemainingSingleSpace = (nRemainingSpace-nNormalSpacingWidth)/(nNumberOfColumns+1);
+ nXPadding += nRemainingSingleSpace;
+ nXOffset += nRemainingSingleSpace;
+ }
+ }
+ }
+ else if( eExpansion == ::com::sun::star::chart::ChartLegendExpansion_HIGH )
{
sal_Int32 nMaxNumberOfRows = nMaxEntryHeight
? (rAvailableSpace.Height - 2*nYPadding ) / nMaxEntryHeight
@@ -308,7 +517,7 @@ void lcl_placeLegendEntries(
static_cast< double >( nNumberOfColumns ) ))
: 0;
}
- else if( eExpansion == LegendExpansion_WIDE )
+ else if( eExpansion == ::com::sun::star::chart::ChartLegendExpansion_WIDE )
{
sal_Int32 nMaxNumberOfColumns = nMaxEntryWidth
? (rAvailableSpace.Width - 2*nXPadding ) / nMaxEntryWidth
@@ -325,7 +534,7 @@ void lcl_placeLegendEntries(
static_cast< double >( nNumberOfRows ) ))
: 0;
}
- else // LegendExpansion_BALANCED
+ else // ::com::sun::star::chart::ChartLegendExpansion_BALANCED
{
double fAspect = nMaxEntryHeight
? static_cast< double >( nMaxEntryWidth ) / static_cast< double >( nMaxEntryHeight )
@@ -341,93 +550,90 @@ void lcl_placeLegendEntries(
}
if(nNumberOfRows<=0)
- return;
+ return aResultingLegendSize;
- // calculate maximum height for current row
- std::vector< sal_Int32 > nMaxHeights( nNumberOfRows );
- sal_Int32 nRow = 0;
- sal_Int32 nColumn = 0;
- for( ; nRow < nNumberOfRows; ++nRow )
+ if( eExpansion != ::com::sun::star::chart::ChartLegendExpansion_CUSTOM )
{
- sal_Int32 nMaxHeight = 0;
- for( nColumn = 0; nColumn < nNumberOfColumns; ++nColumn )
- {
- sal_Int32 nEntry = ( eExpansion == LegendExpansion_WIDE )
- ? (nColumn + nRow * nNumberOfColumns)
- // HIGH or BALANCED
- : (nRow + nColumn * nNumberOfRows);
- if( nEntry < nNumberOfEntries )
- nMaxHeight = ::std::max(
- nMaxHeight, nYOffset + aTextShapes[ nEntry ]->getSize().Height );
- }
- nMaxHeights[ nRow ] = nMaxHeight;
+ lcl_collectColumnWidths( aColumnWidths, nNumberOfRows, nNumberOfColumns, aTextShapes, nSymbolPlusDistanceWidth );
+ lcl_collectRowHeighs( aRowHeights, nNumberOfRows, nNumberOfColumns, aTextShapes );
+ nTextLineHeight = lcl_getTextLineHeight( aRowHeights, nNumberOfRows, fViewFontSize );
}
- // place entries ordered in optimal-width columns
+ sal_Int32 nCurrentXPos = nXPadding;
+ sal_Int32 nCurrentYPos = nYPadding;
+ if( !bSymbolsLeftSide )
+ nCurrentXPos = -nXPadding;
+
+ // place entries into column and rows
sal_Int32 nMaxYPos = 0;
+ sal_Int32 nRow = 0;
+ sal_Int32 nColumn = 0;
for( nColumn = 0; nColumn < nNumberOfColumns; ++nColumn )
{
- sal_Int32 nMaxWidth = 0;
nCurrentYPos = nYPadding;
-
for( nRow = 0; nRow < nNumberOfRows; ++nRow )
{
- sal_Int32 nEntry = ( eExpansion == LegendExpansion_WIDE )
- ? (nColumn + nRow * nNumberOfColumns)
- // HIGH or BALANCED
- : (nRow + nColumn * nNumberOfRows);
-
+ sal_Int32 nEntry = (nColumn + nRow * nNumberOfColumns);
if( nEntry >= nNumberOfEntries )
break;
+ // text shape
+ Reference< drawing::XShape > xTextShape( aTextShapes[nEntry] );
+ if( xTextShape.is() )
+ {
+ awt::Size aTextSize( xTextShape->getSize() );
+ sal_Int32 nTextXPos = nCurrentXPos + nSymbolPlusDistanceWidth;
+ if( !bSymbolsLeftSide )
+ nTextXPos = nCurrentXPos - nSymbolPlusDistanceWidth - aTextSize.Width;
+ xTextShape->setPosition( awt::Point( nTextXPos, nCurrentYPos ));
+ }
+
// symbol
Reference< drawing::XShape > xSymbol( rEntries[ nEntry ].aSymbol );
-
if( xSymbol.is() )
{
- // Note: aspect ratio should always be 3:2
-
- // set symbol size to 75% of maximum space
- awt::Size aSymbolSize(
- aMaxSymbolExtent.Width * 75 / 100,
- aMaxSymbolExtent.Height * 75 / 100 );
- xSymbol->setSize( aSymbolSize );
- sal_Int32 nSymbolXPos = nCurrentXPos + ((aMaxSymbolExtent.Width - aSymbolSize.Width) / 2);
+ awt::Size aSymbolSize( rMaxSymbolExtent );
+ sal_Int32 nSymbolXPos = nCurrentXPos;
if( !bSymbolsLeftSide )
- nSymbolXPos = nSymbolXPos - aMaxSymbolExtent.Width;
-
- // #i109336# Improve auto positioning in chart
- sal_Int32 nTextHeight = nMaxHeights[ nRow ] - nYOffset;
- sal_Int32 nFontSize = static_cast< sal_Int32 >( fViewFontSize );
- sal_Int32 nMaxRowHeight = ( ( ( nTextHeight / nFontSize ) <= 1 ) ? nTextHeight : nFontSize );
- sal_Int32 nSymbolYPos = nCurrentYPos + ( ( nMaxRowHeight - aSymbolSize.Height ) / 2 );
+ nSymbolXPos = nCurrentXPos - rMaxSymbolExtent.Width;
+ sal_Int32 nSymbolYPos = nCurrentYPos + ( ( nTextLineHeight - aSymbolSize.Height ) / 2 );
xSymbol->setPosition( awt::Point( nSymbolXPos, nSymbolYPos ) );
}
- // position text shape
- awt::Size aTextSize( aTextShapes[ nEntry ]->getSize());
- nMaxWidth = ::std::max( nMaxWidth, 2 * nXOffset + aMaxSymbolExtent.Width + aTextSize.Width );
- sal_Int32 nTextXPos = nCurrentXPos + aMaxSymbolExtent.Width;
- if( !bSymbolsLeftSide )
- nTextXPos = nCurrentXPos - aMaxSymbolExtent.Width - aTextSize.Width;
- aTextShapes[ nEntry ]->setPosition( awt::Point( nTextXPos, nCurrentYPos ));
-
- nCurrentYPos += nMaxHeights[ nRow ];
+ nCurrentYPos += aRowHeights[ nRow ];
+ if( nRow+1 < nNumberOfRows )
+ nCurrentYPos += nYOffset;
nMaxYPos = ::std::max( nMaxYPos, nCurrentYPos );
}
if( bSymbolsLeftSide )
- nCurrentXPos += nMaxWidth;
+ {
+ nCurrentXPos += aColumnWidths[nColumn];
+ if( nColumn+1 < nNumberOfColumns )
+ nCurrentXPos += nXOffset;
+ }
else
- nCurrentXPos -= nMaxWidth;
+ {
+ nCurrentXPos -= aColumnWidths[nColumn];
+ if( nColumn+1 < nNumberOfColumns )
+ nCurrentXPos -= nXOffset;
+ }
}
- if( bSymbolsLeftSide )
- rOutLegendSize.Width = nCurrentXPos + nXPadding;
- else
+ if( !bIsCustomSize )
{
- sal_Int32 nLegendWidth = -(nCurrentXPos-nXPadding);
- rOutLegendSize.Width = nLegendWidth;
+ if( bSymbolsLeftSide )
+ aResultingLegendSize.Width = nCurrentXPos + nXPadding;
+ else
+ {
+ sal_Int32 nLegendWidth = -(nCurrentXPos-nXPadding);
+ aResultingLegendSize.Width = nLegendWidth;
+ }
+ aResultingLegendSize.Height = nMaxYPos + nYPadding;
+ }
+ if( !bSymbolsLeftSide )
+ {
+ sal_Int32 nLegendWidth = aResultingLegendSize.Width;
awt::Point aPos(0,0);
for( sal_Int32 nEntry=0; nEntry<nNumberOfEntries; nEntry++ )
{
@@ -441,7 +647,8 @@ void lcl_placeLegendEntries(
xText->setPosition( aPos );
}
}
- rOutLegendSize.Height = nMaxYPos + nYPadding;
+
+ return aResultingLegendSize;
}
// #i109336# Improve auto positioning in chart
@@ -583,14 +790,6 @@ awt::Point lcl_calculatePositionAndRemainingSpace(
return aResult;
}
-template< class T >
-void lcl_appendSeqToVector( const Sequence< T > & rSource, ::std::vector< T > & rDest )
-{
- const sal_Int32 nCount = rSource.getLength();
- for( sal_Int32 i = 0; i < nCount; ++i )
- rDest.push_back( rSource[ i ] );
-}
-
bool lcl_shouldSymbolsBePlacedOnTheLeftSide( const Reference< beans::XPropertySet >& xLegendProp, sal_Int16 nDefaultWritingMode )
{
bool bSymbolsLeftSide = true;
@@ -706,23 +905,26 @@ void VLegend::createShapes(
tPropertyValues aLineFillProperties;
tPropertyValues aTextProperties;
- // limit the width of texts to 30% of the total available width
- // #i109336# Improve auto positioning in chart
- sal_Int32 nMaxLabelWidth = rAvailableSpace.Width * 3 / 10;
Reference< beans::XPropertySet > xLegendProp( m_xLegend, uno::UNO_QUERY );
- LegendExpansion eExpansion = LegendExpansion_HIGH;
+ ::com::sun::star::chart::ChartLegendExpansion eExpansion = ::com::sun::star::chart::ChartLegendExpansion_HIGH;
+ awt::Size aLegendSize( rAvailableSpace );
+
if( xLegendProp.is())
{
// get Expansion property
xLegendProp->getPropertyValue( C2U( "Expansion" )) >>= eExpansion;
- if( eExpansion == LegendExpansion_WIDE )
+ if( eExpansion == ::com::sun::star::chart::ChartLegendExpansion_CUSTOM )
{
- //#i80377#
- nMaxLabelWidth = (rAvailableSpace.Width * 5) / 6;//completely correct would be available width minus symbol size minus distances to page ...
+ RelativeSize aRelativeSize;
+ if ((xLegendProp->getPropertyValue( C2U( "RelativeSize" )) >>= aRelativeSize))
+ {
+ aLegendSize.Width = aRelativeSize.Primary * rPageSize.Width;
+ aLegendSize.Height = aRelativeSize.Secondary * rPageSize.Height;
+ }
+ else
+ eExpansion = ::com::sun::star::chart::ChartLegendExpansion_HIGH;
}
-
- lcl_getProperties( xLegendProp, aLineFillProperties, aTextProperties, nMaxLabelWidth,
- rPageSize );
+ lcl_getProperties( xLegendProp, aLineFillProperties, aTextProperties, rPageSize );
}
if( xBorder.is())
@@ -739,32 +941,47 @@ void VLegend::createShapes(
}
// create entries
- tViewLegendEntryContainer aViewEntries;
+ double fViewFontSize = lcl_CalcViewFontSize( xLegendProp, rPageSize );//todo
+ // #i109336# Improve auto positioning in chart
+ sal_Int32 nSymbolHeigth = static_cast< sal_Int32 >( fViewFontSize * 0.6 );
+ sal_Int32 nSymbolWidth = static_cast< sal_Int32 >( nSymbolHeigth );
+
+ ::std::vector< LegendEntryProvider* >::const_iterator aIter = m_aLegendEntryProviderList.begin();
+ const ::std::vector< LegendEntryProvider* >::const_iterator aEnd = m_aLegendEntryProviderList.end();
+ for( aIter = m_aLegendEntryProviderList.begin(); aIter != aEnd; aIter++ )
{
- ::std::vector< LegendEntryProvider* >::const_iterator aIter = m_aLegendEntryProviderList.begin();
- const ::std::vector< LegendEntryProvider* >::const_iterator aEnd = m_aLegendEntryProviderList.end();
- for( ; aIter != aEnd; aIter++ )
+ LegendEntryProvider* pLegendEntryProvider( *aIter );
+ if( pLegendEntryProvider )
{
- LegendEntryProvider* pLegendEntryProvider( *aIter );
- if( pLegendEntryProvider )
+ awt::Size aCurrentRatio = pLegendEntryProvider->getPreferredLegendKeyAspectRatio();
+ sal_Int32 nCurrentWidth = aCurrentRatio.Width;
+ if( aCurrentRatio.Height > 0 )
{
- lcl_appendSeqToVector< ViewLegendEntry >(
- pLegendEntryProvider->createLegendEntries( eExpansion, xLegendProp, xLegendContainer, m_xShapeFactory, m_xContext )
- , aViewEntries );
+ nCurrentWidth = nSymbolHeigth* aCurrentRatio.Width/aCurrentRatio.Height;
}
+ nSymbolWidth = std::max( nSymbolWidth, nCurrentWidth );
+ }
+ }
+ awt::Size aMaxSymbolExtent( nSymbolWidth, nSymbolHeigth );
+
+ tViewLegendEntryContainer aViewEntries;
+ for( aIter = m_aLegendEntryProviderList.begin(); aIter != aEnd; aIter++ )
+ {
+ LegendEntryProvider* pLegendEntryProvider( *aIter );
+ if( pLegendEntryProvider )
+ {
+ std::vector< ViewLegendEntry > aNewEntries = pLegendEntryProvider->createLegendEntries( aMaxSymbolExtent, eExpansion, xLegendProp, xLegendContainer, m_xShapeFactory, m_xContext );
+ aViewEntries.insert( aViewEntries.end(), aNewEntries.begin(), aNewEntries.end() );
}
}
bool bSymbolsLeftSide = lcl_shouldSymbolsBePlacedOnTheLeftSide( xLegendProp, m_nDefaultWritingMode );
// place entries
- awt::Size aLegendSize;
- lcl_placeLegendEntries( aViewEntries, eExpansion, bSymbolsLeftSide
- , xLegendProp, aTextProperties
- , xLegendContainer, m_xShapeFactory, m_xContext
- , rAvailableSpace, rPageSize, aLegendSize );
+ aLegendSize = lcl_placeLegendEntries( aViewEntries, eExpansion, bSymbolsLeftSide, fViewFontSize, aMaxSymbolExtent
+ , aTextProperties, xLegendContainer, m_xShapeFactory, aLegendSize );
- if( xBorder.is())
+ if( xBorder.is() )
xBorder->setSize( aLegendSize );
}
}
diff --git a/chart2/source/view/main/VLegendSymbolFactory.cxx b/chart2/source/view/main/VLegendSymbolFactory.cxx
index d29b28e8dbe9..b7168bd7ee9f 100644
--- a/chart2/source/view/main/VLegendSymbolFactory.cxx
+++ b/chart2/source/view/main/VLegendSymbolFactory.cxx
@@ -38,9 +38,6 @@
// header for define DBG_ASSERT
#include <tools/debug.hxx>
-// uncomment to disable line dashes at the border of boxes
-// #define DISABLE_DASHES_AT_BORDER
-
using namespace ::com::sun::star;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Sequence;
@@ -105,16 +102,16 @@ namespace chart
{
Reference< drawing::XShape > VLegendSymbolFactory::createSymbol(
+ const awt::Size& rEntryKeyAspectRatio,
const Reference< drawing::XShapes > xSymbolContainer,
- chart2::LegendSymbolStyle eStyle,
+ LegendSymbolStyle eStyle,
const Reference< lang::XMultiServiceFactory > & xShapeFactory,
const Reference< beans::XPropertySet > & xLegendEntryProperties,
tPropertyType ePropertyType, const uno::Any& rExplicitSymbol )
{
Reference< drawing::XShape > xResult;
- if( ! (xSymbolContainer.is() &&
- xShapeFactory.is()))
+ if( ! (xSymbolContainer.is() && xShapeFactory.is()))
return xResult;
xResult.set( xShapeFactory->createInstance(
@@ -124,247 +121,92 @@ Reference< drawing::XShape > VLegendSymbolFactory::createSymbol(
if( ! xResultGroup.is())
return xResult;
- // aspect ratio of symbols is always 3:2
- awt::Size aBoundSize( 3000, 2000 );
- bool bUseBox = false;
-
// add an invisible square box to maintain aspect ratio
- switch( eStyle )
- {
- case chart2::LegendSymbolStyle_BOX:
- case chart2::LegendSymbolStyle_HORIZONTAL_LINE:
- case chart2::LegendSymbolStyle_VERTICAL_LINE:
- case chart2::LegendSymbolStyle_DIAGONAL_LINE:
- case chart2::LegendSymbolStyle_LINE_WITH_BOX:
- case chart2::LegendSymbolStyle_LINE_WITH_SYMBOL:
- case chart2::LegendSymbolStyle_CIRCLE:
- {
- Reference< drawing::XShape > xBound( ShapeFactory(xShapeFactory).createInvisibleRectangle(
- xResultGroup, aBoundSize ));
- break;
- }
-
- case chart2::LegendSymbolStyle_BAR:
- case chart2::LegendSymbolStyle_RECTANGLE:
- case chart2::LegendSymbolStyle_STRETCHED_RECTANGLE:
- case chart2::LegendSymbolStyle_USER_DEFINED:
- default:
- break;
- }
+ Reference< drawing::XShape > xBound( ShapeFactory(xShapeFactory).createInvisibleRectangle(
+ xResultGroup, rEntryKeyAspectRatio ));
// create symbol
- switch( eStyle )
+ try
{
- case chart2::LegendSymbolStyle_BOX:
- case chart2::LegendSymbolStyle_BAR:
- case chart2::LegendSymbolStyle_RECTANGLE:
- case chart2::LegendSymbolStyle_STRETCHED_RECTANGLE:
- case chart2::LegendSymbolStyle_CIRCLE:
+ if( eStyle == LegendSymbolStyle_LINE )
{
- try
+ Reference< drawing::XShape > xLine( xShapeFactory->createInstance(
+ C2U( "com.sun.star.drawing.LineShape" )), uno::UNO_QUERY );
+ if( xLine.is())
{
- Reference< drawing::XShape > xShape;
+ xResultGroup->add( xLine );
+ xLine->setSize( awt::Size( rEntryKeyAspectRatio.Width, 0 ));
+ xLine->setPosition( awt::Point( 0, rEntryKeyAspectRatio.Height/2 ));
- if( eStyle == chart2::LegendSymbolStyle_CIRCLE )
- xShape.set( xShapeFactory->createInstance(
- C2U( "com.sun.star.drawing.EllipseShape" )), uno::UNO_QUERY );
- else
- xShape.set( xShapeFactory->createInstance(
- C2U( "com.sun.star.drawing.RectangleShape" )), uno::UNO_QUERY );
+ lcl_setPropetiesToShape( xLegendEntryProperties, xLine, ePropertyType );
+ }
- if( xShape.is())
+ Reference< drawing::XShape > xSymbol;
+ const sal_Int32 nSize = std::min(rEntryKeyAspectRatio.Width,rEntryKeyAspectRatio.Height);
+ chart2::Symbol aSymbol;
+ if( rExplicitSymbol >>= aSymbol )
+ {
+ drawing::Direction3D aSymbolSize( nSize, nSize, 0 );
+ drawing::Position3D aPos( rEntryKeyAspectRatio.Width/2, rEntryKeyAspectRatio.Height/2, 0 );
+ ShapeFactory aFactory( xShapeFactory );
+ if( aSymbol.Style == chart2::SymbolStyle_STANDARD )
{
- xResultGroup->add( xShape );
- if( eStyle == chart2::LegendSymbolStyle_BOX ||
- eStyle == chart2::LegendSymbolStyle_CIRCLE )
- {
- xShape->setSize( awt::Size( 2000, 2000 ));
- xShape->setPosition( awt::Point( 500, 0 ));
- }
- else
- {
- xShape->setSize( aBoundSize );
- }
+ // take series color as fill color
+ xLegendEntryProperties->getPropertyValue( C2U("Color")) >>= aSymbol.FillColor;
+ // border of symbols always same as fill color
+ aSymbol.BorderColor = aSymbol.FillColor;
+
+ xSymbol.set( aFactory.createSymbol2D(
+ xResultGroup,
+ aPos,
+ aSymbolSize,
+ aSymbol.StandardSymbol,
+ aSymbol.BorderColor,
+ aSymbol.FillColor ));
}
-
- lcl_setPropetiesToShape( xLegendEntryProperties, xShape, ePropertyType ); // PROP_TYPE_FILLED_SERIES );
-
-#ifdef DISABLE_DASHES_AT_BORDER
- // don't allow dashed border style
- Reference< beans::XPropertySet > xShapeProp( xShape, uno::UNO_QUERY );
- if( xShapeProp.is())
+ else if( aSymbol.Style == chart2::SymbolStyle_GRAPHIC )
{
- drawing::LineStyle aLineStyle;
- if( ( xShapeProp->getPropertyValue( C2U("LineStyle")) >>= aLineStyle ) &&
- aLineStyle == drawing::LineStyle_DASH )
- {
- aLineStyle = drawing::LineStyle_SOLID;
- xShapeProp->setPropertyValue( C2U("LineStyle"), uno::makeAny( aLineStyle ));
- }
+ xSymbol.set( aFactory.createGraphic2D(
+ xResultGroup,
+ aPos,
+ aSymbolSize,
+ aSymbol.Graphic ));
}
-#endif
- }
- catch( uno::Exception & ex )
- {
- ASSERT_EXCEPTION( ex );
- }
- break;
- }
-
- case chart2::LegendSymbolStyle_HORIZONTAL_LINE:
- {
- try
- {
- Reference< drawing::XShape > xLine(
- xShapeFactory->createInstance(
- C2U( "com.sun.star.drawing.LineShape" )), uno::UNO_QUERY );
- if( xLine.is())
+ else if( aSymbol.Style == chart2::SymbolStyle_AUTO )
{
- xResultGroup->add( xLine );
- xLine->setSize( awt::Size( 3000, 0 ));
- xLine->setPosition( awt::Point( 0, 1000 ));
-
- lcl_setPropetiesToShape( xLegendEntryProperties, xLine, ePropertyType ); // PROP_TYPE_LINE_SERIES );
+ DBG_ERROR("the given parameter is not allowed to contain an automatic symbol style");
}
}
- catch( uno::Exception & ex )
- {
- ASSERT_EXCEPTION( ex );
- }
- break;
}
-
- case chart2::LegendSymbolStyle_VERTICAL_LINE:
+ else if( eStyle == LegendSymbolStyle_CIRCLE )
{
- try
+ Reference< drawing::XShape > xShape( xShapeFactory->createInstance(
+ C2U( "com.sun.star.drawing.EllipseShape" )), uno::UNO_QUERY );
+ if( xShape.is() )
{
- Reference< drawing::XShape > xLine(
- xShapeFactory->createInstance(
- C2U( "com.sun.star.drawing.LineShape" )), uno::UNO_QUERY );
- if( xLine.is())
- {
- xResultGroup->add( xLine );
- xLine->setSize( awt::Size( 0, 2000 ));
- xLine->setPosition( awt::Point( 1500, 0 ));
-
- lcl_setPropetiesToShape( xLegendEntryProperties, xLine, ePropertyType ); // PROP_TYPE_LINE_SERIES );
- }
- }
- catch( uno::Exception & ex )
- {
- ASSERT_EXCEPTION( ex );
+ xResultGroup->add( xShape );
+ sal_Int32 nSize = std::min( rEntryKeyAspectRatio.Width, rEntryKeyAspectRatio.Height );
+ xShape->setSize( awt::Size( nSize, nSize ) );
+ xShape->setPosition( awt::Point( rEntryKeyAspectRatio.Width/2-nSize/2, rEntryKeyAspectRatio.Height/2-nSize/2 ) );
+ lcl_setPropetiesToShape( xLegendEntryProperties, xShape, ePropertyType ); // PROP_TYPE_FILLED_SERIES );
}
- break;
}
-
- case chart2::LegendSymbolStyle_DIAGONAL_LINE:
+ else // eStyle == LegendSymbolStyle_BOX
{
- try
+ Reference< drawing::XShape > xShape( xShapeFactory->createInstance(
+ C2U( "com.sun.star.drawing.RectangleShape" )), uno::UNO_QUERY );
+ if( xShape.is() )
{
- Reference< drawing::XShape > xLine(
- xShapeFactory->createInstance(
- C2U( "com.sun.star.drawing.LineShape" )), uno::UNO_QUERY );
- if( xLine.is())
- {
- xResultGroup->add( xLine );
- xLine->setSize( awt::Size( 2000, 2000 ));
- xLine->setPosition( awt::Point( 500, 0 ));
-
- lcl_setPropetiesToShape( xLegendEntryProperties, xLine, ePropertyType ); // PROP_TYPE_LINE_SERIES );
- }
- }
- catch( uno::Exception & ex )
- {
- ASSERT_EXCEPTION( ex );
+ xResultGroup->add( xShape );
+ xShape->setSize( rEntryKeyAspectRatio );
+ xShape->setPosition( awt::Point( 0, 0 ) );
+ lcl_setPropetiesToShape( xLegendEntryProperties, xShape, ePropertyType ); // PROP_TYPE_FILLED_SERIES );
}
- break;
}
-
- case chart2::LegendSymbolStyle_LINE_WITH_BOX:
- bUseBox = true;
- // fall-through intended
- case chart2::LegendSymbolStyle_LINE_WITH_SYMBOL:
- try
- {
- Reference< drawing::XShape > xLine(
- xShapeFactory->createInstance(
- C2U( "com.sun.star.drawing.LineShape" )), uno::UNO_QUERY );
- if( xLine.is())
- {
- xResultGroup->add( xLine );
- xLine->setSize( awt::Size( 3000, 0 ));
- xLine->setPosition( awt::Point( 0, 1000 ));
-
- lcl_setPropetiesToShape( xLegendEntryProperties, xLine, ePropertyType );
- }
-
- Reference< drawing::XShape > xSymbol;
- const sal_Int32 nSize = 1500;
- if( bUseBox )
- {
- xSymbol.set( xShapeFactory->createInstance(
- C2U( "com.sun.star.drawing.RectangleShape" )), uno::UNO_QUERY );
- xResultGroup->add( xSymbol );
-
- if( xSymbol.is())
- {
- xSymbol->setSize( awt::Size( nSize, nSize ));
- xSymbol->setPosition( awt::Point( 1500 - nSize/2, 1000 - nSize/2 ));
-
- lcl_setPropetiesToShape( xLegendEntryProperties, xSymbol, ePropertyType );
- }
- }
- else
- {
- chart2::Symbol aSymbol;
-
- if( rExplicitSymbol >>= aSymbol )
- {
- drawing::Direction3D aSymbolSize( nSize, nSize, 0 );
- drawing::Position3D aPos( 1500, 1000, 0 );
- ShapeFactory aFactory( xShapeFactory );
- if( aSymbol.Style == chart2::SymbolStyle_STANDARD )
- {
- // take series color as fill color
- xLegendEntryProperties->getPropertyValue( C2U("Color")) >>= aSymbol.FillColor;
- // border of symbols always same as fill color
- aSymbol.BorderColor = aSymbol.FillColor;
-
- xSymbol.set( aFactory.createSymbol2D(
- xResultGroup,
- aPos,
- aSymbolSize,
- aSymbol.StandardSymbol,
- aSymbol.BorderColor,
- aSymbol.FillColor ));
- }
- else if( aSymbol.Style == chart2::SymbolStyle_GRAPHIC )
- {
- xSymbol.set( aFactory.createGraphic2D(
- xResultGroup,
- aPos,
- aSymbolSize,
- aSymbol.Graphic ));
- }
- else if( aSymbol.Style == chart2::SymbolStyle_AUTO )
- {
- DBG_ERROR("the given parameter is not allowed to contain an automatic symbol style");
- }
- }
- }
- }
- catch( uno::Exception & ex )
- {
- ASSERT_EXCEPTION( ex );
- }
- break;
-
- case chart2::LegendSymbolStyle_USER_DEFINED:
- break;
-
- default:
- // just to remove warning (there is an auto-generated extra label)
- break;
+ }
+ catch( uno::Exception & ex )
+ {
+ ASSERT_EXCEPTION( ex );
}
return xResult;