1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: VLegend.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_chart2.hxx"
33 #include "VLegend.hxx"
35 #include "PropertyMapper.hxx"
36 #include "CommonConverters.hxx"
37 #include "ObjectIdentifier.hxx"
38 #include "RelativePositionHelper.hxx"
39 #include "ShapeFactory.hxx"
40 #include "RelativeSizeHelper.hxx"
41 #include "LegendEntryProvider.hxx"
42 #include <com/sun/star/text/XTextRange.hpp>
43 #include <com/sun/star/text/WritingMode2.hpp>
44 #include <com/sun/star/beans/XPropertySet.hpp>
45 #include <com/sun/star/beans/XPropertyState.hpp>
46 #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
47 #include <com/sun/star/drawing/LineJoint.hpp>
48 #include <com/sun/star/chart2/LegendExpansion.hpp>
49 #include <com/sun/star/chart2/LegendPosition.hpp>
50 #include <com/sun/star/chart2/RelativePosition.hpp>
51 #include <rtl/ustrbuf.hxx>
52 #include <svtools/languageoptions.hxx>
57 using namespace ::com::sun::star
;
58 using namespace ::com::sun::star::chart2
;
60 using ::com::sun::star::uno::Reference
;
61 using ::com::sun::star::uno::Sequence
;
62 using ::rtl::OUString
;
63 using ::rtl::OUStringBuffer
;
65 //.............................................................................
68 //.............................................................................
73 typedef ::std::pair
< ::chart::tNameSequence
, ::chart::tAnySequence
> tPropertyValues
;
75 typedef ::std::vector
< ViewLegendEntry
> tViewLegendEntryContainer
;
77 double lcl_CalcViewFontSize(
78 const Reference
< beans::XPropertySet
> & xProp
,
79 const awt::Size
& rReferenceSize
)
81 double fResult
= 10.0;
83 awt::Size aPropRefSize
;
84 float fFontHeight( 0.0 );
85 if( xProp
.is() && ( xProp
->getPropertyValue( C2U( "CharHeight" )) >>= fFontHeight
))
87 fResult
= fFontHeight
;
90 if( (xProp
->getPropertyValue( C2U( "ReferencePageSize" )) >>= aPropRefSize
) &&
91 (aPropRefSize
.Height
> 0))
93 // todo: find out if asian text is really used
94 // Reference< beans::XPropertySetInfo >xInfo( xProp, uno::UNO_QUERY );
95 // float fFontHeight2 = fFontHeight;
97 // xInfo->hasPropertyByName(C2U("CharHeightAsian")) &&
98 // (xProp->getPropertyValue(C2U("CharHeightAsian")) >>= fFontHeight2) &&
99 // fFontHeight2 > fFontHeight )
101 // fFontHeight = fFontHeight2;
105 // xInfo->hasPropertyByName(C2U("CharHeightComplex")) &&
106 // (xProp->getPropertyValue(C2U("CharHeightComplex")) >>= fFontHeight2) &&
107 // fFontHeight2 > fFontHeight )
109 // fFontHeight = fFontHeight2;
112 fResult
= ::chart::RelativeSizeHelper::calculate( fFontHeight
, aPropRefSize
, rReferenceSize
);
115 catch( const uno::Exception
& ex
)
117 ASSERT_EXCEPTION( ex
);
122 return (fResult
* (2540.0 / 72.0));
125 void lcl_getProperties(
126 const Reference
< beans::XPropertySet
> & xLegendProp
,
127 tPropertyValues
& rOutLineFillProperties
,
128 tPropertyValues
& rOutTextProperties
,
129 sal_Int32 nMaxLabelWidth
,
130 const awt::Size
& rReferenceSize
)
132 // Get Line- and FillProperties from model legend
133 if( xLegendProp
.is())
135 // set rOutLineFillProperties
136 ::chart::tPropertyNameValueMap aLineFillValueMap
;
137 ::chart::PropertyMapper::getValueMap( aLineFillValueMap
, ::chart::PropertyMapper::getPropertyNameMapForFillAndLineProperties(), xLegendProp
);
139 aLineFillValueMap
[ C2U("LineJoint") ] = uno::makeAny( drawing::LineJoint_ROUND
);
141 ::chart::PropertyMapper::getMultiPropertyListsFromValueMap(
142 rOutLineFillProperties
.first
, rOutLineFillProperties
.second
, aLineFillValueMap
);
144 // set rOutTextProperties
145 ::chart::tPropertyNameValueMap aTextValueMap
;
146 ::chart::PropertyMapper::getValueMap( aTextValueMap
, ::chart::PropertyMapper::getPropertyNameMapForCharacterProperties(), xLegendProp
);
148 drawing::TextHorizontalAdjust
eHorizAdjust( drawing::TextHorizontalAdjust_LEFT
);
149 aTextValueMap
[ C2U("TextAutoGrowHeight") ] = uno::makeAny( sal_True
);
150 aTextValueMap
[ C2U("TextAutoGrowWidth") ] = uno::makeAny( sal_True
);
151 aTextValueMap
[ C2U("TextHorizontalAdjust") ] = uno::makeAny( eHorizAdjust
);
152 aTextValueMap
[ C2U("TextMaximumFrameWidth") ] = uno::makeAny( nMaxLabelWidth
);
154 // recalculate font size
155 awt::Size aPropRefSize
;
156 float fFontHeight( 0.0 );
157 if( (xLegendProp
->getPropertyValue( C2U( "ReferencePageSize" )) >>= aPropRefSize
) &&
158 (aPropRefSize
.Height
> 0) &&
159 (aTextValueMap
[ C2U("CharHeight") ] >>= fFontHeight
) )
161 aTextValueMap
[ C2U("CharHeight") ] = uno::makeAny(
162 static_cast< float >(
163 ::chart::RelativeSizeHelper::calculate( fFontHeight
, aPropRefSize
, rReferenceSize
)));
165 if( aTextValueMap
[ C2U("CharHeightAsian") ] >>= fFontHeight
)
167 aTextValueMap
[ C2U("CharHeightAsian") ] = uno::makeAny(
168 static_cast< float >(
169 ::chart::RelativeSizeHelper::calculate( fFontHeight
, aPropRefSize
, rReferenceSize
)));
171 if( aTextValueMap
[ C2U("CharHeightComplex") ] >>= fFontHeight
)
173 aTextValueMap
[ C2U("CharHeightComplex") ] = uno::makeAny(
174 static_cast< float >(
175 ::chart::RelativeSizeHelper::calculate( fFontHeight
, aPropRefSize
, rReferenceSize
)));
179 ::chart::PropertyMapper::getMultiPropertyListsFromValueMap(
180 rOutTextProperties
.first
, rOutTextProperties
.second
, aTextValueMap
);
184 awt::Size
lcl_createTextShapes(
185 const tViewLegendEntryContainer
& rEntries
,
186 const Reference
< lang::XMultiServiceFactory
> & xShapeFactory
,
187 const Reference
< drawing::XShapes
> & xTarget
,
188 ::std::vector
< Reference
< drawing::XShape
> > & rOutTextShapes
,
189 const tPropertyValues
& rTextProperties
)
193 for( tViewLegendEntryContainer::const_iterator
aIt( rEntries
.begin());
194 aIt
!= rEntries
.end(); ++aIt
)
198 // create label shape
199 Reference
< drawing::XShape
> xGroupShapeForSingleEntry(
200 xShapeFactory
->createInstance(
201 C2U( "com.sun.star.drawing.GroupShape" )), uno::UNO_QUERY_THROW
);
202 Reference
< drawing::XShape
>xEntry(
203 xShapeFactory
->createInstance(
204 C2U( "com.sun.star.drawing.TextShape" )), uno::UNO_QUERY_THROW
);
205 xTarget
->add( xGroupShapeForSingleEntry
);
207 Reference
< drawing::XShapes
> xGroup( xGroupShapeForSingleEntry
, uno::UNO_QUERY_THROW
);
208 xGroup
->add( xEntry
);
211 Sequence
< Reference
< XFormattedString
> > aLabelSeq
= (*aIt
).aLabel
;
212 for( sal_Int32 i
= 0; i
< aLabelSeq
.getLength(); ++i
)
214 // todo: support more than one text range
218 Reference
< text::XTextRange
> xRange( xEntry
, uno::UNO_QUERY
);
219 OUString
aLabelString( aLabelSeq
[i
]->getString());
220 // workaround for Issue #i67540#
221 if( !aLabelString
.getLength())
222 aLabelString
= C2U(" ");
224 xRange
->setString( aLabelString
);
226 PropertyMapper::setMultiProperties(
227 rTextProperties
.first
, rTextProperties
.second
,
228 Reference
< beans::XPropertySet
>( xRange
, uno::UNO_QUERY
));
231 awt::Size
aCurrSize( xEntry
->getSize());
232 aResult
.Width
= ::std::max( aResult
.Width
, aCurrSize
.Width
);
233 aResult
.Height
= ::std::max( aResult
.Height
, aCurrSize
.Height
);
236 rOutTextShapes
.push_back( xGroupShapeForSingleEntry
);
238 catch( uno::Exception
& ex
)
240 ASSERT_EXCEPTION( ex
);
248 void lcl_placeLegendEntries(
249 const tViewLegendEntryContainer
& rEntries
,
250 LegendExpansion eExpansion
,
251 bool bSymbolsLeftSide
,
252 const Reference
< beans::XPropertySet
> & xProperties
,
253 tPropertyValues
& rTextProperties
,
254 const Reference
< drawing::XShapes
> & xTarget
,
255 const Reference
< lang::XMultiServiceFactory
> & xShapeFactory
,
256 const Reference
< uno::XComponentContext
> & /* xContext */,
257 const awt::Size
& rAvailableSpace
,
258 const awt::Size
& rPageSize
,
259 awt::Size
& rOutLegendSize
)
261 double fViewFontSize
= lcl_CalcViewFontSize( xProperties
, rPageSize
);
263 // padding as percentage of the font height
264 double fXPadding
= (1.0 / 5.0);
265 double fYPadding
= (1.0 / 3.0);
266 double fXOffset
= (1.0 / 5.0);
267 double fYOffset
= (1.0 / 5.0);
269 const sal_Int32 nXPadding
= static_cast< sal_Int32
>( fViewFontSize
* fXPadding
);
270 const sal_Int32 nYPadding
= static_cast< sal_Int32
>( fViewFontSize
* fYPadding
);
271 const sal_Int32 nXOffset
= static_cast< sal_Int32
>( fViewFontSize
* fXOffset
);
272 const sal_Int32 nYOffset
= static_cast< sal_Int32
>( fViewFontSize
* fYOffset
);
274 ::std::vector
< Reference
< drawing::XShape
> > aTextShapes
;
275 awt::Size aMaxEntryExtent
= lcl_createTextShapes(
276 rEntries
, xShapeFactory
, xTarget
, aTextShapes
, rTextProperties
);
277 OSL_ASSERT( aTextShapes
.size() == rEntries
.size());
279 awt::Size
aMaxSymbolExtent( static_cast< sal_Int32
>( fViewFontSize
* 3.0 / 2.0 ),
280 static_cast< sal_Int32
>( fViewFontSize
));
281 sal_Int32 nCurrentXPos
= nXPadding
;
282 sal_Int32 nCurrentYPos
= nYPadding
;
283 sal_Int32 nMaxEntryWidth
= 2 * nXOffset
+ aMaxSymbolExtent
.Width
+ aMaxEntryExtent
.Width
;
284 sal_Int32 nMaxEntryHeight
= nYOffset
+ aMaxEntryExtent
.Height
;
285 sal_Int32 nNumberOfEntries
= rEntries
.size();
287 if( !bSymbolsLeftSide
)
288 nCurrentXPos
= -nXPadding
;
290 sal_Int32 nNumberOfColumns
= 0, nNumberOfRows
= 0;
292 // determine layout depending on LegendExpansion
293 if( eExpansion
== LegendExpansion_HIGH
)
295 sal_Int32 nMaxNumberOfRows
= nMaxEntryHeight
296 ? (rAvailableSpace
.Height
- 2*nYPadding
) / nMaxEntryHeight
299 nNumberOfColumns
= nMaxNumberOfRows
300 ? static_cast< sal_Int32
>(
301 ceil( static_cast< double >( nNumberOfEntries
) /
302 static_cast< double >( nMaxNumberOfRows
) ))
304 nNumberOfRows
= nNumberOfColumns
305 ? static_cast< sal_Int32
>(
306 ceil( static_cast< double >( nNumberOfEntries
) /
307 static_cast< double >( nNumberOfColumns
) ))
310 else if( eExpansion
== LegendExpansion_WIDE
)
312 sal_Int32 nMaxNumberOfColumns
= nMaxEntryWidth
313 ? (rAvailableSpace
.Width
- 2*nXPadding
) / nMaxEntryWidth
316 nNumberOfRows
= nMaxNumberOfColumns
317 ? static_cast< sal_Int32
>(
318 ceil( static_cast< double >( nNumberOfEntries
) /
319 static_cast< double >( nMaxNumberOfColumns
) ))
321 nNumberOfColumns
= nNumberOfRows
322 ? static_cast< sal_Int32
>(
323 ceil( static_cast< double >( nNumberOfEntries
) /
324 static_cast< double >( nNumberOfRows
) ))
327 else // LegendExpansion_BALANCED
329 double fAspect
= nMaxEntryHeight
330 ? static_cast< double >( nMaxEntryWidth
) / static_cast< double >( nMaxEntryHeight
)
333 nNumberOfRows
= static_cast< sal_Int32
>(
334 ceil( sqrt( static_cast< double >( nNumberOfEntries
) * fAspect
)));
335 nNumberOfColumns
= nNumberOfRows
336 ? static_cast< sal_Int32
>(
337 ceil( static_cast< double >( nNumberOfEntries
) /
338 static_cast< double >( nNumberOfRows
) ))
345 // calculate maximum height for current row
346 std::vector
< sal_Int32
> nMaxHeights( nNumberOfRows
);
348 sal_Int32 nColumn
= 0;
349 for( ; nRow
< nNumberOfRows
; ++nRow
)
351 sal_Int32 nMaxHeight
= 0;
352 for( nColumn
= 0; nColumn
< nNumberOfColumns
; ++nColumn
)
354 sal_Int32 nEntry
= ( eExpansion
== LegendExpansion_WIDE
)
355 ? (nColumn
+ nRow
* nNumberOfColumns
)
357 : (nRow
+ nColumn
* nNumberOfRows
);
358 if( nEntry
< nNumberOfEntries
)
359 nMaxHeight
= ::std::max(
360 nMaxHeight
, nYOffset
+ aTextShapes
[ nEntry
]->getSize().Height
);
362 nMaxHeights
[ nRow
] = nMaxHeight
;
365 // place entries ordered in optimal-width columns
366 sal_Int32 nMaxYPos
= 0;
367 for( nColumn
= 0; nColumn
< nNumberOfColumns
; ++nColumn
)
369 sal_Int32 nMaxWidth
= 0;
370 nCurrentYPos
= nYPadding
;
372 for( nRow
= 0; nRow
< nNumberOfRows
; ++nRow
)
374 sal_Int32 nEntry
= ( eExpansion
== LegendExpansion_WIDE
)
375 ? (nColumn
+ nRow
* nNumberOfColumns
)
377 : (nRow
+ nColumn
* nNumberOfRows
);
379 if( nEntry
>= nNumberOfEntries
)
383 Reference
< drawing::XShape
> xSymbol( rEntries
[ nEntry
].aSymbol
);
387 // Note: aspect ratio should always be 3:2
389 // set symbol size to 75% of maximum space
390 awt::Size
aSymbolSize(
391 aMaxSymbolExtent
.Width
* 75 / 100,
392 aMaxSymbolExtent
.Height
* 75 / 100 );
393 xSymbol
->setSize( aSymbolSize
);
394 sal_Int32 nSymbolXPos
= nCurrentXPos
+ ((aMaxSymbolExtent
.Width
- aSymbolSize
.Width
) / 2);
395 if( !bSymbolsLeftSide
)
396 nSymbolXPos
= nSymbolXPos
- aMaxSymbolExtent
.Width
;
397 xSymbol
->setPosition( awt::Point( nSymbolXPos
,
398 nCurrentYPos
+ ((aMaxSymbolExtent
.Height
- aSymbolSize
.Height
) / 2)));
401 // position text shape
402 awt::Size
aTextSize( aTextShapes
[ nEntry
]->getSize());
403 nMaxWidth
= ::std::max( nMaxWidth
, 2 * nXOffset
+ aMaxSymbolExtent
.Width
+ aTextSize
.Width
);
404 sal_Int32 nTextXPos
= nCurrentXPos
+ aMaxSymbolExtent
.Width
;
405 if( !bSymbolsLeftSide
)
406 nTextXPos
= nCurrentXPos
- aMaxSymbolExtent
.Width
- aTextSize
.Width
;
407 aTextShapes
[ nEntry
]->setPosition( awt::Point( nTextXPos
, nCurrentYPos
));
409 nCurrentYPos
+= nMaxHeights
[ nRow
];
410 nMaxYPos
= ::std::max( nMaxYPos
, nCurrentYPos
);
412 if( bSymbolsLeftSide
)
413 nCurrentXPos
+= nMaxWidth
;
415 nCurrentXPos
-= nMaxWidth
;
418 if( bSymbolsLeftSide
)
419 rOutLegendSize
.Width
= nCurrentXPos
+ nXPadding
;
422 sal_Int32 nLegendWidth
= -(nCurrentXPos
-nXPadding
);
423 rOutLegendSize
.Width
= nLegendWidth
;
425 awt::Point
aPos(0,0);
426 for( sal_Int32 nEntry
=0; nEntry
<nNumberOfEntries
; nEntry
++ )
428 Reference
< drawing::XShape
> xSymbol( rEntries
[ nEntry
].aSymbol
);
429 aPos
= xSymbol
->getPosition();
430 aPos
.X
+= nLegendWidth
;
431 xSymbol
->setPosition( aPos
);
432 Reference
< drawing::XShape
> xText( aTextShapes
[ nEntry
] );
433 aPos
= xText
->getPosition();
434 aPos
.X
+= nLegendWidth
;
435 xText
->setPosition( aPos
);
438 rOutLegendSize
.Height
= nMaxYPos
+ nYPadding
;
441 double lcl_getPageLayoutDistancePercentage()
446 chart2::RelativePosition
lcl_getDefaultPosition( LegendPosition ePos
, const awt::Rectangle
& rOutAvailableSpace
, const awt::Size
& rPageSize
)
448 // shift legend about 2% of page size into the primary direction by default
449 const double fDefaultDistance
= lcl_getPageLayoutDistancePercentage();
450 chart2::RelativePosition aResult
;
454 case LegendPosition_LINE_START
:
455 aResult
= chart2::RelativePosition(
456 fDefaultDistance
, 0.5, drawing::Alignment_LEFT
);
458 case LegendPosition_LINE_END
:
459 aResult
= chart2::RelativePosition(
460 1.0 - fDefaultDistance
, 0.5, drawing::Alignment_RIGHT
);
462 case LegendPosition_PAGE_START
:
464 double fDistance
= (static_cast<double>(rOutAvailableSpace
.Y
)/static_cast<double>(rPageSize
.Height
)) + fDefaultDistance
;
465 aResult
= chart2::RelativePosition(
466 0.5, fDistance
, drawing::Alignment_TOP
);
469 case LegendPosition_PAGE_END
:
470 aResult
= chart2::RelativePosition(
471 0.5, 1.0 - fDefaultDistance
, drawing::Alignment_BOTTOM
);
474 case LegendPosition_CUSTOM
:
476 case LegendPosition_MAKE_FIXED_SIZE
:
485 a point relative to the upper left corner that can be used for
486 XShape::setPosition()
488 awt::Point
lcl_calculatePositionAndRemainingSpace(
489 awt::Rectangle
& rRemainingSpace
,
490 const awt::Size
& rPageSize
,
491 chart2::RelativePosition aRelPos
,
493 const awt::Size
& aLegendSize
)
495 // calculate position
497 static_cast< sal_Int32
>( aRelPos
.Primary
* rPageSize
.Width
),
498 static_cast< sal_Int32
>( aRelPos
.Secondary
* rPageSize
.Height
));
500 aResult
= RelativePositionHelper::getUpperLeftCornerOfAnchoredObject(
501 aResult
, aLegendSize
, aRelPos
.Anchor
);
503 // adapt rRemainingSpace if LegendPosition is not CUSTOM
504 sal_Int32 nYDistance
= static_cast<sal_Int32
>(rPageSize
.Height
*lcl_getPageLayoutDistancePercentage());
505 sal_Int32 nXDistance
= static_cast<sal_Int32
>(rPageSize
.Width
*lcl_getPageLayoutDistancePercentage());
506 rRemainingSpace
.Width
-=nXDistance
;
507 rRemainingSpace
.Height
-=nYDistance
;
510 case LegendPosition_LINE_START
:
512 sal_Int32 nExtent
= aLegendSize
.Width
;
513 rRemainingSpace
.Width
-= nExtent
;
514 rRemainingSpace
.X
+= ( nExtent
+ nXDistance
);
517 case LegendPosition_LINE_END
:
518 rRemainingSpace
.Width
-= ( aLegendSize
.Width
);
520 case LegendPosition_PAGE_START
:
522 sal_Int32 nExtent
= aLegendSize
.Height
;
523 rRemainingSpace
.Height
-= nExtent
;
524 rRemainingSpace
.Y
+= ( nExtent
+ nYDistance
);
527 case LegendPosition_PAGE_END
:
528 rRemainingSpace
.Height
-= ( aLegendSize
.Height
);
536 // adjust the legend position. Esp. for old files that had slightly smaller legends
537 const sal_Int32
nEdgeDistance( 30 );
538 if( aResult
.X
+ aLegendSize
.Width
> rPageSize
.Width
)
540 sal_Int32
nNewX( (rPageSize
.Width
- aLegendSize
.Width
) - nEdgeDistance
);
541 if( nNewX
> rPageSize
.Width
/ 4 )
544 if( aResult
.Y
+ aLegendSize
.Height
> rPageSize
.Height
)
546 sal_Int32
nNewY( (rPageSize
.Height
- aLegendSize
.Height
) - nEdgeDistance
);
547 if( nNewY
> rPageSize
.Height
/ 4 )
555 void lcl_appendSeqToVector( const Sequence
< T
> & rSource
, ::std::vector
< T
> & rDest
)
557 const sal_Int32 nCount
= rSource
.getLength();
558 for( sal_Int32 i
= 0; i
< nCount
; ++i
)
559 rDest
.push_back( rSource
[ i
] );
562 bool lcl_shouldSymbolsBePlacedOnTheLeftSide( const Reference
< beans::XPropertySet
>& xLegendProp
, sal_Int16 nDefaultWritingMode
)
564 bool bSymbolsLeftSide
= true;
567 if( SvtLanguageOptions().IsCTLFontEnabled() )
571 sal_Int16 nWritingMode
=-1;
572 if( (xLegendProp
->getPropertyValue( C2U("WritingMode") ) >>= nWritingMode
) )
574 if( nWritingMode
== text::WritingMode2::PAGE
)
575 nWritingMode
= nDefaultWritingMode
;
576 if( nWritingMode
== text::WritingMode2::RL_TB
)
577 bSymbolsLeftSide
=false;
582 catch( uno::Exception
& ex
)
584 ASSERT_EXCEPTION( ex
);
586 return bSymbolsLeftSide
;
589 } // anonymous namespace
592 const Reference
< XLegend
> & xLegend
,
593 const Reference
< uno::XComponentContext
> & xContext
,
594 const std::vector
< LegendEntryProvider
* >& rLegendEntryProviderList
) :
595 m_xLegend( xLegend
),
596 m_xContext( xContext
),
597 m_aLegendEntryProviderList( rLegendEntryProviderList
)
601 // ----------------------------------------
603 void SAL_CALL
VLegend::init(
604 const Reference
< drawing::XShapes
>& xTargetPage
,
605 const Reference
< lang::XMultiServiceFactory
>& xFactory
,
606 const Reference
< frame::XModel
>& xModel
)
608 m_xTarget
= xTargetPage
;
609 m_xShapeFactory
= xFactory
;
613 // ----------------------------------------
615 void VLegend::setDefaultWritingMode( sal_Int16 nDefaultWritingMode
)
617 m_nDefaultWritingMode
= nDefaultWritingMode
;
620 // ----------------------------------------
623 bool VLegend::isVisible( const Reference
< XLegend
> & xLegend
)
628 sal_Bool bShow
= sal_False
;
631 Reference
< beans::XPropertySet
> xLegendProp( xLegend
, uno::UNO_QUERY_THROW
);
632 xLegendProp
->getPropertyValue( C2U( "Show" )) >>= bShow
;
634 catch( uno::Exception
& ex
)
636 ASSERT_EXCEPTION( ex
);
642 // ----------------------------------------
644 void VLegend::createShapes(
645 const awt::Size
& rAvailableSpace
,
646 const awt::Size
& rPageSize
)
648 if(! (m_xLegend
.is() &&
649 m_xShapeFactory
.is() &&
655 //create shape and add to page
656 m_xShape
.set( m_xShapeFactory
->createInstance(
657 C2U( "com.sun.star.drawing.GroupShape" )), uno::UNO_QUERY
);
658 m_xTarget
->add( m_xShape
);
660 // set name to enable selection
662 OUString
aLegendParticle( ObjectIdentifier::createParticleForLegend( m_xLegend
, m_xModel
) );
663 ShapeFactory::setShapeName( m_xShape
, ObjectIdentifier::createClassifiedIdentifierForParticle( aLegendParticle
) );
666 // create and insert sub-shapes
667 Reference
< drawing::XShapes
> xLegendContainer( m_xShape
, uno::UNO_QUERY
);
668 if( xLegendContainer
.is())
670 Reference
< drawing::XShape
> xBorder(
671 m_xShapeFactory
->createInstance(
672 C2U( "com.sun.star.drawing.RectangleShape" )), uno::UNO_QUERY
);
674 // for quickly setting properties
675 tPropertyValues aLineFillProperties
;
676 tPropertyValues aTextProperties
;
678 // limit the width of texts to 20% of the total available width
679 sal_Int32 nMaxLabelWidth
= rAvailableSpace
.Width
/ 5;
680 Reference
< beans::XPropertySet
> xLegendProp( m_xLegend
, uno::UNO_QUERY
);
681 LegendExpansion eExpansion
= LegendExpansion_HIGH
;
682 if( xLegendProp
.is())
684 lcl_getProperties( xLegendProp
, aLineFillProperties
, aTextProperties
, nMaxLabelWidth
,
687 // get Expansion property
688 xLegendProp
->getPropertyValue( C2U( "Expansion" )) >>= eExpansion
;
693 xLegendContainer
->add( xBorder
);
695 // apply legend properties
696 PropertyMapper::setMultiProperties(
697 aLineFillProperties
.first
, aLineFillProperties
.second
,
698 Reference
< beans::XPropertySet
>( xBorder
, uno::UNO_QUERY
));
700 //because of this name this border will be used for marking the legend
701 ShapeFactory(m_xShapeFactory
).setShapeName( xBorder
, C2U("MarkHandles") );
705 tViewLegendEntryContainer aViewEntries
;
707 ::std::vector
< LegendEntryProvider
* >::const_iterator aIter
= m_aLegendEntryProviderList
.begin();
708 const ::std::vector
< LegendEntryProvider
* >::const_iterator aEnd
= m_aLegendEntryProviderList
.end();
709 for( ; aIter
!= aEnd
; aIter
++ )
711 LegendEntryProvider
* pLegendEntryProvider( *aIter
);
712 if( pLegendEntryProvider
)
714 lcl_appendSeqToVector
< ViewLegendEntry
>(
715 pLegendEntryProvider
->createLegendEntries( eExpansion
, xLegendProp
, xLegendContainer
, m_xShapeFactory
, m_xContext
)
721 bool bSymbolsLeftSide
= lcl_shouldSymbolsBePlacedOnTheLeftSide( xLegendProp
, m_nDefaultWritingMode
);
724 awt::Size aLegendSize
;
725 lcl_placeLegendEntries( aViewEntries
, eExpansion
, bSymbolsLeftSide
726 , xLegendProp
, aTextProperties
727 , xLegendContainer
, m_xShapeFactory
, m_xContext
728 , rAvailableSpace
, rPageSize
, aLegendSize
);
731 xBorder
->setSize( aLegendSize
);
734 catch( uno::Exception
& ex
)
736 ASSERT_EXCEPTION( ex
);
740 // ----------------------------------------
742 void VLegend::changePosition(
743 awt::Rectangle
& rOutAvailableSpace
,
744 const awt::Size
& rPageSize
)
751 // determine position and alignment depending on default position
752 awt::Size aLegendSize
= m_xShape
->getSize();
753 Reference
< beans::XPropertySet
> xLegendProp( m_xLegend
, uno::UNO_QUERY_THROW
);
754 chart2::RelativePosition aRelativePosition
;
757 ! (xLegendProp
->getPropertyValue( C2U( "RelativePosition" )) >>= aRelativePosition
);
759 LegendPosition ePos
= LegendPosition_CUSTOM
;
760 xLegendProp
->getPropertyValue( C2U( "AnchorPosition" )) >>= ePos
;
765 // auto position: relative to remaining space
766 aRelativePosition
= lcl_getDefaultPosition( ePos
, rOutAvailableSpace
, rPageSize
);
767 awt::Point aPos
= lcl_calculatePositionAndRemainingSpace(
768 rOutAvailableSpace
, rPageSize
, aRelativePosition
, ePos
, aLegendSize
);
769 m_xShape
->setPosition( aPos
);
773 // manual position: relative to whole page
774 awt::Rectangle
aAvailableSpace( 0, 0, rPageSize
.Width
, rPageSize
.Height
);
775 awt::Point aPos
= lcl_calculatePositionAndRemainingSpace(
776 aAvailableSpace
, rPageSize
, aRelativePosition
, ePos
, aLegendSize
);
777 m_xShape
->setPosition( aPos
);
779 if( ePos
!= LegendPosition_CUSTOM
)
781 // calculate remaining space as if having autoposition:
782 aRelativePosition
= lcl_getDefaultPosition( ePos
, rOutAvailableSpace
, rPageSize
);
783 lcl_calculatePositionAndRemainingSpace(
784 rOutAvailableSpace
, rPageSize
, aRelativePosition
, ePos
, aLegendSize
);
788 catch( uno::Exception
& ex
)
790 ASSERT_EXCEPTION( ex
);
794 //.............................................................................
796 //.............................................................................