LibreOffice Module chart2 (master) 1
VLegend.cxx
Go to the documentation of this file.
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 "VButton.hxx"
22#include <Legend.hxx>
23#include <PropertyMapper.hxx>
24#include <ChartModel.hxx>
25#include <ObjectIdentifier.hxx>
26#include <FormattedString.hxx>
28#include <ShapeFactory.hxx>
32#include <com/sun/star/text/WritingMode2.hpp>
33#include <com/sun/star/beans/XPropertySet.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 <com/sun/star/chart2/RelativeSize.hpp>
40#include <com/sun/star/chart2/XFormattedString2.hpp>
41#include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp>
42#include <com/sun/star/chart2/data/PivotTableFieldEntry.hpp>
43#include <rtl/math.hxx>
44#include <svl/ctloptions.hxx>
47
48#include <utility>
49#include <vector>
50#include <algorithm>
51
52using namespace ::com::sun::star;
53using namespace ::com::sun::star::chart2;
54
55using ::com::sun::star::uno::Reference;
56using ::com::sun::star::uno::Sequence;
57
58namespace chart
59{
60
61namespace
62{
63
64typedef std::pair< ::chart::tNameSequence, ::chart::tAnySequence > tPropertyValues;
65
66double lcl_CalcViewFontSize(
67 const Reference< beans::XPropertySet > & xProp,
68 const awt::Size & rReferenceSize )
69{
70 double fResult = 10.0;
71
72 float fFontHeight( 0.0 );
73 if( xProp.is() && ( xProp->getPropertyValue( "CharHeight") >>= fFontHeight ))
74 {
75 fResult = fFontHeight;
76 try
77 {
78 awt::Size aPropRefSize;
79 if( (xProp->getPropertyValue( "ReferencePageSize") >>= aPropRefSize) &&
80 (aPropRefSize.Height > 0))
81 {
82 fResult = ::chart::RelativeSizeHelper::calculate( fFontHeight, aPropRefSize, rReferenceSize );
83 }
84 }
85 catch( const uno::Exception & )
86 {
88 }
89 }
90
91 return convertPointToMm100(fResult);
92}
93
94void lcl_getProperties(
95 const Reference< beans::XPropertySet > & xLegendProp,
96 tPropertyValues & rOutLineFillProperties,
97 tPropertyValues & rOutTextProperties,
98 const awt::Size & rReferenceSize )
99{
100 // Get Line- and FillProperties from model legend
101 if( !xLegendProp.is())
102 return;
103
104 // set rOutLineFillProperties
105 ::chart::tPropertyNameValueMap aLineFillValueMap;
107
108 aLineFillValueMap[ "LineJoint" ] <<= drawing::LineJoint_ROUND;
109
111 rOutLineFillProperties.first, rOutLineFillProperties.second, aLineFillValueMap );
112
113 // set rOutTextProperties
114 ::chart::tPropertyNameValueMap aTextValueMap;
116
117 aTextValueMap[ "TextAutoGrowHeight" ] <<= true;
118 aTextValueMap[ "TextAutoGrowWidth" ] <<= true;
119 aTextValueMap[ "TextHorizontalAdjust" ] <<= drawing::TextHorizontalAdjust_LEFT;
120 aTextValueMap[ "TextMaximumFrameWidth" ] <<= rReferenceSize.Width; //needs to be overwritten by actual available space in the legend
121
122 // recalculate font size
123 awt::Size aPropRefSize;
124 float fFontHeight( 0.0 );
125 if( (xLegendProp->getPropertyValue( "ReferencePageSize") >>= aPropRefSize) &&
126 (aPropRefSize.Height > 0) &&
127 (aTextValueMap[ "CharHeight" ] >>= fFontHeight) )
128 {
129 aTextValueMap[ "CharHeight" ] <<=
130 static_cast< float >(
131 ::chart::RelativeSizeHelper::calculate( fFontHeight, aPropRefSize, rReferenceSize ));
132
133 if( aTextValueMap[ "CharHeightAsian" ] >>= fFontHeight )
134 {
135 aTextValueMap[ "CharHeightAsian" ] <<=
136 static_cast< float >(
137 ::chart::RelativeSizeHelper::calculate( fFontHeight, aPropRefSize, rReferenceSize ));
138 }
139 if( aTextValueMap[ "CharHeightComplex" ] >>= fFontHeight )
140 {
141 aTextValueMap[ "CharHeightComplex" ] <<=
142 static_cast< float >(
143 ::chart::RelativeSizeHelper::calculate( fFontHeight, aPropRefSize, rReferenceSize ));
144 }
145 }
146
148 rOutTextProperties.first, rOutTextProperties.second, aTextValueMap );
149}
150
151awt::Size lcl_createTextShapes(
152 const std::vector<ViewLegendEntry> & rEntries,
153 const rtl::Reference<SvxShapeGroupAnyD> & xTarget,
154 std::vector< rtl::Reference<SvxShapeText> > & rOutTextShapes,
155 const tPropertyValues & rTextProperties )
156{
157 awt::Size aResult;
158
159 for (ViewLegendEntry const & rEntry : rEntries)
160 {
161 try
162 {
163 OUString aLabelString;
164 if (rEntry.xLabel)
165 {
166 // tdf#150034 limit legend label text
167 if (rEntry.xLabel->getString().getLength() > 520)
168 {
169 sal_Int32 nIndex = rEntry.xLabel->getString().indexOf(' ', 500);
170 rEntry.xLabel->setString(
171 rEntry.xLabel->getString().copy(0, nIndex > 500 ? nIndex : 500));
172 }
173
174 aLabelString += rEntry.xLabel->getString();
175 // workaround for Issue #i67540#
176 if( aLabelString.isEmpty())
177 aLabelString = " ";
178 }
179
181 ShapeFactory::createText( xTarget, aLabelString,
182 rTextProperties.first, rTextProperties.second, uno::Any() );
183
184 // adapt max-extent
185 awt::Size aCurrSize( xEntry->getSize());
186 aResult.Width = std::max( aResult.Width, aCurrSize.Width );
187 aResult.Height = std::max( aResult.Height, aCurrSize.Height );
188
189 rOutTextShapes.push_back( xEntry );
190 }
191 catch( const uno::Exception & )
192 {
193 DBG_UNHANDLED_EXCEPTION("chart2");
194 }
195 }
196
197 return aResult;
198}
199
200void lcl_collectColumnWidths( std::vector< sal_Int32 >& rColumnWidths, const sal_Int32 nNumberOfRows, const sal_Int32 nNumberOfColumns,
201 const std::vector< rtl::Reference<SvxShapeText> >& rTextShapes, sal_Int32 nSymbolPlusDistanceWidth )
202{
203 rColumnWidths.clear();
204 sal_Int32 nNumberOfEntries = rTextShapes.size();
205 for (sal_Int32 nRow = 0; nRow < nNumberOfRows; ++nRow )
206 {
207 for (sal_Int32 nColumn = 0; nColumn < nNumberOfColumns; ++nColumn )
208 {
209 sal_Int32 nEntry = nColumn + nRow * nNumberOfColumns;
210 if( nEntry < nNumberOfEntries )
211 {
212 awt::Size aTextSize( rTextShapes[ nEntry ]->getSize() );
213 sal_Int32 nWidth = nSymbolPlusDistanceWidth + aTextSize.Width;
214 if( nRow==0 )
215 rColumnWidths.push_back( nWidth );
216 else
217 rColumnWidths[nColumn] = std::max( nWidth, rColumnWidths[nColumn] );
218 }
219 }
220 }
221}
222
223void lcl_collectRowHeighs( std::vector< sal_Int32 >& rRowHeights, const sal_Int32 nNumberOfRows, const sal_Int32 nNumberOfColumns,
224 const std::vector< rtl::Reference<SvxShapeText> >& rTextShapes )
225{
226 // calculate maximum height for each row
227 // and collect column widths
228 rRowHeights.clear();
229 sal_Int32 nNumberOfEntries = rTextShapes.size();
230 for (sal_Int32 nRow = 0; nRow < nNumberOfRows; ++nRow)
231 {
232 sal_Int32 nCurrentRowHeight = 0;
233 for (sal_Int32 nColumn = 0; nColumn < nNumberOfColumns; ++nColumn)
234 {
235 sal_Int32 nEntry = nColumn + nRow * nNumberOfColumns;
236 if( nEntry < nNumberOfEntries )
237 {
238 awt::Size aTextSize( rTextShapes[ nEntry ]->getSize() );
239 nCurrentRowHeight = std::max( nCurrentRowHeight, aTextSize.Height );
240 }
241 }
242 rRowHeights.push_back( nCurrentRowHeight );
243 }
244}
245
246sal_Int32 lcl_getTextLineHeight( const std::vector< sal_Int32 >& aRowHeights, const sal_Int32 nNumberOfRows, double fViewFontSize )
247{
248 const sal_Int32 nFontHeight = static_cast< sal_Int32 >( fViewFontSize );
249 if (!nFontHeight)
250 return 0;
251 sal_Int32 nTextLineHeight = nFontHeight;
252 for (sal_Int32 nRow = 0; nRow < nNumberOfRows; ++nRow)
253 {
254 sal_Int32 nFullTextHeight = aRowHeights[nRow];
255 if( ( nFullTextHeight / nFontHeight ) <= 1 )
256 {
257 nTextLineHeight = nFullTextHeight;//found an entry with one line-> have real text height
258 break;
259 }
260 }
261 return nTextLineHeight;
262}
263
264//returns resulting legend size
265awt::Size lcl_placeLegendEntries(
266 std::vector<ViewLegendEntry> & rEntries,
267 css::chart::ChartLegendExpansion eExpansion,
268 bool bSymbolsLeftSide,
269 double fViewFontSize,
270 const awt::Size& rMaxSymbolExtent,
271 tPropertyValues & rTextProperties,
272 const rtl::Reference<SvxShapeGroupAnyD> & xTarget,
273 const awt::Size& rRemainingSpace,
274 sal_Int32 nYStartPosition,
275 const awt::Size& rPageSize,
276 bool bIsPivotChart,
277 awt::Size& rDefaultLegendSize)
278{
279 bool bIsCustomSize = (eExpansion == css::chart::ChartLegendExpansion_CUSTOM);
280 awt::Size aResultingLegendSize(0,0);
281 // For Pivot charts set the *minimum* legend size as a function of page size.
282 if ( bIsPivotChart )
283 aResultingLegendSize = awt::Size((rPageSize.Width * 13) / 80, (rPageSize.Height * 31) / 90);
284 if( bIsCustomSize )
285 aResultingLegendSize = awt::Size(rRemainingSpace.Width, rRemainingSpace.Height + nYStartPosition);
286
287 // #i109336# Improve auto positioning in chart
288 sal_Int32 nXPadding = static_cast< sal_Int32 >( std::max( 100.0, fViewFontSize * 0.33 ) );
289 sal_Int32 nXOffset = static_cast< sal_Int32 >( std::max( 100.0, fViewFontSize * 0.66 ) );
290 sal_Int32 nYPadding = static_cast< sal_Int32 >( std::max( 100.0, fViewFontSize * 0.2 ) );
291 sal_Int32 nYOffset = static_cast< sal_Int32 >( std::max( 100.0, fViewFontSize * 0.2 ) );
292
293 const sal_Int32 nSymbolToTextDistance = static_cast< sal_Int32 >( std::max( 100.0, fViewFontSize * 0.22 ) );//minimum 1mm
294 const sal_Int32 nSymbolPlusDistanceWidth = rMaxSymbolExtent.Width + nSymbolToTextDistance;
295 sal_Int32 nMaxTextWidth = rRemainingSpace.Width - nSymbolPlusDistanceWidth;
296 uno::Any* pFrameWidthAny = PropertyMapper::getValuePointer( rTextProperties.second, rTextProperties.first, u"TextMaximumFrameWidth");
297 if(pFrameWidthAny)
298 {
299 if( eExpansion == css::chart::ChartLegendExpansion_HIGH )
300 {
301 // limit the width of texts to 30% of the total available width
302 // #i109336# Improve auto positioning in chart
303 nMaxTextWidth = rRemainingSpace.Width * 3 / 10;
304 }
305 *pFrameWidthAny <<= nMaxTextWidth;
306 }
307
308 std::vector< rtl::Reference<SvxShapeText> > aTextShapes;
309 awt::Size aMaxEntryExtent = lcl_createTextShapes( rEntries, xTarget, aTextShapes, rTextProperties );
310 OSL_ASSERT( aTextShapes.size() == rEntries.size());
311
312 sal_Int32 nMaxEntryWidth = nXOffset + nSymbolPlusDistanceWidth + aMaxEntryExtent.Width;
313 sal_Int32 nMaxEntryHeight = nYOffset + aMaxEntryExtent.Height;
314 sal_Int32 nNumberOfEntries = rEntries.size();
315
316 rDefaultLegendSize.Width = nMaxEntryWidth;
317 rDefaultLegendSize.Height = nMaxEntryHeight + nYPadding;
318
319 sal_Int32 nNumberOfColumns = 0, nNumberOfRows = 0;
320 std::vector< sal_Int32 > aColumnWidths;
321 std::vector< sal_Int32 > aRowHeights;
322
323 sal_Int32 nTextLineHeight = static_cast< sal_Int32 >( fViewFontSize );
324
325 // determine layout depending on LegendExpansion
326 if( eExpansion == css::chart::ChartLegendExpansion_CUSTOM )
327 {
328 sal_Int32 nCurrentRow=0;
329 sal_Int32 nCurrentColumn=-1;
330 sal_Int32 nMaxColumnCount=-1;
331 for( sal_Int32 nN=0; nN<static_cast<sal_Int32>(aTextShapes.size()); nN++ )
332 {
333 rtl::Reference<SvxShapeText> xShape( aTextShapes[nN] );
334 if( !xShape.is() )
335 continue;
336 awt::Size aSize( xShape->getSize() );
337 sal_Int32 nNewWidth = aSize.Width + nSymbolPlusDistanceWidth;
338 sal_Int32 nCurrentColumnCount = aColumnWidths.size();
339
340 //are we allowed to add a new column?
341 if( nMaxColumnCount==-1 || (nCurrentColumn+1) < nMaxColumnCount )
342 {
343 //try add a new column
344 nCurrentColumn++;
345 if( nCurrentColumn < nCurrentColumnCount )
346 {
347 //check whether the current column width is sufficient for the new entry
348 if( aColumnWidths[nCurrentColumn]>=nNewWidth )
349 {
350 //all good proceed with next entry
351 continue;
352 }
353
354 aColumnWidths[nCurrentColumn] = std::max( nNewWidth, aColumnWidths[nCurrentColumn] );
355 } else
356 aColumnWidths.push_back(nNewWidth);
357
358 //do the columns still fit into the given size?
359 nCurrentColumnCount = aColumnWidths.size();//update count
360 sal_Int32 nSumWidth = 0;
361 for (sal_Int32 nColumn = 0; nColumn < nCurrentColumnCount; nColumn++)
362 nSumWidth += aColumnWidths[nColumn];
363
364 if( nSumWidth <= rRemainingSpace.Width || nCurrentColumnCount==1 )
365 {
366 //all good proceed with next entry
367 continue;
368 }
369 else
370 {
371 //not enough space for the current amount of columns
372 //try again with less columns
373 nMaxColumnCount = nCurrentColumnCount-1;
374 nN=-1;
375 nCurrentRow=0;
376 nCurrentColumn=-1;
377 aColumnWidths.clear();
378 }
379 }
380 else
381 {
382 //add a new row and try the same entry again
383 nCurrentRow++;
384 nCurrentColumn=-1;
385 nN--;
386 }
387 }
388 nNumberOfColumns = aColumnWidths.size();
389 nNumberOfRows = nCurrentRow+1;
390
391 //check if there is not enough space so that some entries must be removed
392 lcl_collectRowHeighs( aRowHeights, nNumberOfRows, nNumberOfColumns, aTextShapes );
393 nTextLineHeight = lcl_getTextLineHeight( aRowHeights, nNumberOfRows, fViewFontSize );
394 sal_Int32 nSumHeight = 0;
395 for (sal_Int32 nRow=0; nRow < nNumberOfRows; nRow++)
396 nSumHeight += aRowHeights[nRow];
397 sal_Int32 nRemainingSpace = rRemainingSpace.Height - nSumHeight;
398
399 if( nRemainingSpace < -100 ) // 1mm tolerance for OOXML interop tdf#90404
400 {
401 //remove entries that are too big
402 for (sal_Int32 nRow = nNumberOfRows; nRow--; )
403 {
404 for (sal_Int32 nColumn = nNumberOfColumns; nColumn--; )
405 {
406 sal_Int32 nEntry = nColumn + nRow * nNumberOfColumns;
407 if( nEntry < static_cast<sal_Int32>(aTextShapes.size()) )
408 {
409 DrawModelWrapper::removeShape( aTextShapes[nEntry] );
410 aTextShapes.pop_back();
411 }
412 if( nEntry < nNumberOfEntries && ( nEntry != 0 || nNumberOfColumns != 1 ) )
413 {
414 DrawModelWrapper::removeShape( rEntries[ nEntry ].xSymbol );
415 rEntries.pop_back();
416 nNumberOfEntries--;
417 }
418 }
419 if (nRow == 0 && nNumberOfColumns == 1)
420 {
421 try
422 {
423 OUString aLabelString = rEntries[0].xLabel->getString();
424 static constexpr OUStringLiteral sDots = u"...";
425 for (sal_Int32 nNewLen = aLabelString.getLength() - sDots.getLength(); nNewLen > 0; )
426 {
427 OUString aNewLabel = aLabelString.subView(0, nNewLen) + sDots;
429 xTarget, aNewLabel, rTextProperties.first, rTextProperties.second, uno::Any());
430 nSumHeight = xEntry->getSize().Height;
431 nRemainingSpace = rRemainingSpace.Height - nSumHeight;
432 if (nRemainingSpace >= 0)
433 {
434 sal_Int32 nWidth = xEntry->getSize().Width + nSymbolPlusDistanceWidth;
435 if (rRemainingSpace.Width - nWidth >= 0)
436 {
437 aTextShapes.push_back(xEntry);
438 rEntries[0].xLabel->setString(aNewLabel);
439 aRowHeights[0] = nSumHeight;
440 aColumnWidths[0] = nWidth;
441 break;
442 }
443 }
445 // The intention here is to make pathological cases with extremely large labels
446 // converge a little faster
447 if (nNewLen > 10 && std::abs(nRemainingSpace) > nSumHeight / 10)
448 nNewLen -= nNewLen / 10;
449 else
450 --nNewLen;
451 }
452 if (aTextShapes.size() == 0)
453 {
454 DrawModelWrapper::removeShape(rEntries[0].xSymbol);
455 rEntries.pop_back();
456 nNumberOfEntries--;
457 aRowHeights.pop_back();
458 }
459 }
460 catch (const uno::Exception&)
461 {
462 DBG_UNHANDLED_EXCEPTION("chart2");
463 }
464 }
465 else
466 {
467 nSumHeight -= aRowHeights[nRow];
468 aRowHeights.pop_back();
469 nRemainingSpace = rRemainingSpace.Height - nSumHeight;
470 if (nRemainingSpace >= 0)
471 break;
472 }
473 }
474 nNumberOfRows = static_cast<sal_Int32>(aRowHeights.size());
475 }
476 if( nRemainingSpace >= -100 ) // 1mm tolerance for OOXML interop tdf#90404
477 {
478 sal_Int32 nNormalSpacingHeight = 2*nYPadding+(nNumberOfRows-1)*nYOffset;
479 if( nRemainingSpace < nNormalSpacingHeight )
480 {
481 //reduce spacing between the entries
482 nYPadding = nYOffset = nRemainingSpace/(nNumberOfRows+1);
483 }
484 else
485 {
486 //we have some space left that should be spread equally between all rows
487 sal_Int32 nRemainingSingleSpace = (nRemainingSpace-nNormalSpacingHeight)/(nNumberOfRows+1);
488 nYPadding += nRemainingSingleSpace;
489 nYOffset += nRemainingSingleSpace;
490 }
491 }
492
493 //check spacing between columns
494 sal_Int32 nSumWidth = 0;
495 for (sal_Int32 nColumn = 0; nColumn < nNumberOfColumns; nColumn++)
496 nSumWidth += aColumnWidths[nColumn];
497 nRemainingSpace = rRemainingSpace.Width - nSumWidth;
498 if( nRemainingSpace>=0 )
499 {
500 sal_Int32 nNormalSpacingWidth = 2*nXPadding+(nNumberOfColumns-1)*nXOffset;
501 if( nRemainingSpace < nNormalSpacingWidth )
502 {
503 //reduce spacing between the entries
504 nXPadding = nXOffset = nRemainingSpace/(nNumberOfColumns+1);
505 }
506 else
507 {
508 //we have some space left that should be spread equally between all columns
509 sal_Int32 nRemainingSingleSpace = (nRemainingSpace-nNormalSpacingWidth)/(nNumberOfColumns+1);
510 nXPadding += nRemainingSingleSpace;
511 nXOffset += nRemainingSingleSpace;
512 }
513 }
514 }
515 else if( eExpansion == css::chart::ChartLegendExpansion_HIGH )
516 {
517 sal_Int32 nMaxNumberOfRows = nMaxEntryHeight
518 ? (rRemainingSpace.Height - 2*nYPadding ) / nMaxEntryHeight
519 : 0;
520
521 nNumberOfColumns = nMaxNumberOfRows
522 ? static_cast< sal_Int32 >(
523 ceil( static_cast< double >( nNumberOfEntries ) /
524 static_cast< double >( nMaxNumberOfRows ) ))
525 : 0;
526 nNumberOfRows = nNumberOfColumns
527 ? static_cast< sal_Int32 >(
528 ceil( static_cast< double >( nNumberOfEntries ) /
529 static_cast< double >( nNumberOfColumns ) ))
530 : 0;
531 }
532 else if( eExpansion == css::chart::ChartLegendExpansion_WIDE )
533 {
534 sal_Int32 nMaxNumberOfColumns = nMaxEntryWidth
535 ? (rRemainingSpace.Width - 2*nXPadding ) / nMaxEntryWidth
536 : 0;
537
538 nNumberOfRows = nMaxNumberOfColumns
539 ? static_cast< sal_Int32 >(
540 ceil( static_cast< double >( nNumberOfEntries ) /
541 static_cast< double >( nMaxNumberOfColumns ) ))
542 : 0;
543 nNumberOfColumns = nNumberOfRows
544 ? static_cast< sal_Int32 >(
545 ceil( static_cast< double >( nNumberOfEntries ) /
546 static_cast< double >( nNumberOfRows ) ))
547 : 0;
548 }
549 else // css::chart::ChartLegendExpansion_BALANCED
550 {
551 double fAspect = nMaxEntryHeight
552 ? static_cast< double >( nMaxEntryWidth ) / static_cast< double >( nMaxEntryHeight )
553 : 0.0;
554
555 nNumberOfRows = static_cast< sal_Int32 >(
556 ceil( sqrt( static_cast< double >( nNumberOfEntries ) * fAspect )));
557 nNumberOfColumns = nNumberOfRows
558 ? static_cast< sal_Int32 >(
559 ceil( static_cast< double >( nNumberOfEntries ) /
560 static_cast< double >( nNumberOfRows ) ))
561 : 0;
562 }
563
564 if(nNumberOfRows<=0)
565 return aResultingLegendSize;
566
567 if( eExpansion != css::chart::ChartLegendExpansion_CUSTOM )
568 {
569 lcl_collectColumnWidths( aColumnWidths, nNumberOfRows, nNumberOfColumns, aTextShapes, nSymbolPlusDistanceWidth );
570 lcl_collectRowHeighs( aRowHeights, nNumberOfRows, nNumberOfColumns, aTextShapes );
571 nTextLineHeight = lcl_getTextLineHeight( aRowHeights, nNumberOfRows, fViewFontSize );
572 }
573
574 sal_Int32 nCurrentXPos = bSymbolsLeftSide ? nXPadding : -nXPadding;
575
576 // place entries into column and rows
577 sal_Int32 nMaxYPos = 0;
578
579 for (sal_Int32 nColumn = 0; nColumn < nNumberOfColumns; ++nColumn)
580 {
581 sal_Int32 nCurrentYPos = nYPadding + nYStartPosition;
582 for (sal_Int32 nRow = 0; nRow < nNumberOfRows; ++nRow)
583 {
584 sal_Int32 nEntry = nColumn + nRow * nNumberOfColumns;
585 if( nEntry >= nNumberOfEntries )
586 break;
587
588 // text shape
589 rtl::Reference<SvxShapeText> xTextShape( aTextShapes[nEntry] );
590 if( xTextShape.is() )
591 {
592 awt::Size aTextSize( xTextShape->getSize() );
593 sal_Int32 nTextXPos = nCurrentXPos + nSymbolPlusDistanceWidth;
594 if( !bSymbolsLeftSide )
595 nTextXPos = nCurrentXPos - nSymbolPlusDistanceWidth - aTextSize.Width;
596 xTextShape->setPosition( awt::Point( nTextXPos, nCurrentYPos ));
597 }
598
599 // symbol
600 rtl::Reference<SvxShapeGroup> & xSymbol( rEntries[ nEntry ].xSymbol );
601 if( xSymbol.is() )
602 {
603 awt::Size aSymbolSize( rMaxSymbolExtent );
604 sal_Int32 nSymbolXPos = nCurrentXPos;
605 if( !bSymbolsLeftSide )
606 nSymbolXPos = nCurrentXPos - rMaxSymbolExtent.Width;
607 sal_Int32 nSymbolYPos = nCurrentYPos + ( ( nTextLineHeight - aSymbolSize.Height ) / 2 );
608 xSymbol->setPosition( awt::Point( nSymbolXPos, nSymbolYPos ) );
609 }
610
611 nCurrentYPos += aRowHeights[ nRow ];
612 if( nRow+1 < nNumberOfRows )
613 nCurrentYPos += nYOffset;
614 nMaxYPos = std::max( nMaxYPos, nCurrentYPos );
615 }
616 if( bSymbolsLeftSide )
617 {
618 nCurrentXPos += aColumnWidths[nColumn];
619 if( nColumn+1 < nNumberOfColumns )
620 nCurrentXPos += nXOffset;
621 }
622 else
623 {
624 nCurrentXPos -= aColumnWidths[nColumn];
625 if( nColumn+1 < nNumberOfColumns )
626 nCurrentXPos -= nXOffset;
627 }
628 }
629
630 if( !bIsCustomSize )
631 {
632 if( bSymbolsLeftSide )
633 aResultingLegendSize.Width = std::max( aResultingLegendSize.Width, nCurrentXPos + nXPadding );
634 else
635 {
636 sal_Int32 nLegendWidth = -(nCurrentXPos-nXPadding);
637 aResultingLegendSize.Width = std::max( aResultingLegendSize.Width, nLegendWidth );
638 }
639 aResultingLegendSize.Height = std::max( aResultingLegendSize.Height, nMaxYPos + nYPadding );
640 }
641
642 if( !bSymbolsLeftSide )
643 {
644 sal_Int32 nLegendWidth = aResultingLegendSize.Width;
645 awt::Point aPos(0,0);
646 for( sal_Int32 nEntry=0; nEntry<nNumberOfEntries; nEntry++ )
647 {
648 rtl::Reference<SvxShapeGroup> & xSymbol( rEntries[ nEntry ].xSymbol );
649 aPos = xSymbol->getPosition();
650 aPos.X += nLegendWidth;
651 xSymbol->setPosition( aPos );
652 rtl::Reference<SvxShapeText> & xText( aTextShapes[ nEntry ] );
653 aPos = xText->getPosition();
654 aPos.X += nLegendWidth;
655 xText->setPosition( aPos );
656 }
657 }
658
659 return aResultingLegendSize;
660}
661
662// #i109336# Improve auto positioning in chart
663sal_Int32 lcl_getLegendLeftRightMargin()
664{
665 return 210; // 1/100 mm
666}
667
668// #i109336# Improve auto positioning in chart
669sal_Int32 lcl_getLegendTopBottomMargin()
670{
671 return 185; // 1/100 mm
672}
673
674chart2::RelativePosition lcl_getDefaultPosition( LegendPosition ePos, const awt::Rectangle& rOutAvailableSpace, const awt::Size & rPageSize )
675{
676 chart2::RelativePosition aResult;
677
678 switch( ePos )
679 {
680 case LegendPosition_LINE_START:
681 {
682 // #i109336# Improve auto positioning in chart
683 const double fDefaultDistance = static_cast< double >( lcl_getLegendLeftRightMargin() ) /
684 static_cast< double >( rPageSize.Width );
685 aResult = chart2::RelativePosition(
686 fDefaultDistance, 0.5, drawing::Alignment_LEFT );
687 }
688 break;
689 case LegendPosition_LINE_END:
690 {
691 // #i109336# Improve auto positioning in chart
692 const double fDefaultDistance = static_cast< double >( lcl_getLegendLeftRightMargin() ) /
693 static_cast< double >( rPageSize.Width );
694 aResult = chart2::RelativePosition(
695 1.0 - fDefaultDistance, 0.5, drawing::Alignment_RIGHT );
696 }
697 break;
698 case LegendPosition_PAGE_START:
699 {
700 // #i109336# Improve auto positioning in chart
701 const double fDefaultDistance = static_cast< double >( lcl_getLegendTopBottomMargin() ) /
702 static_cast< double >( rPageSize.Height );
703 double fDistance = (static_cast<double>(rOutAvailableSpace.Y)/static_cast<double>(rPageSize.Height)) + fDefaultDistance;
704 aResult = chart2::RelativePosition(
705 0.5, fDistance, drawing::Alignment_TOP );
706 }
707 break;
708 case LegendPosition_PAGE_END:
709 {
710 // #i109336# Improve auto positioning in chart
711 const double fDefaultDistance = static_cast< double >( lcl_getLegendTopBottomMargin() ) /
712 static_cast< double >( rPageSize.Height );
713
714 double fDistance = double(rPageSize.Height - (rOutAvailableSpace.Y + rOutAvailableSpace.Height));
715 fDistance += fDefaultDistance;
716 fDistance /= double(rPageSize.Height);
717
718 aResult = chart2::RelativePosition(
719 0.5, 1.0 - fDistance, drawing::Alignment_BOTTOM );
720 }
721 break;
722 case LegendPosition::LegendPosition_MAKE_FIXED_SIZE:
723 default:
724 // nothing to be set
725 break;
726 }
727
728 return aResult;
729}
730
735awt::Point lcl_calculatePositionAndRemainingSpace(
736 awt::Rectangle & rRemainingSpace,
737 const awt::Size & rPageSize,
738 const chart2::RelativePosition& rRelPos,
739 LegendPosition ePos,
740 const awt::Size& aLegendSize,
741 bool bOverlay )
742{
743 // calculate position
744 awt::Point aResult(
745 static_cast< sal_Int32 >( rRelPos.Primary * rPageSize.Width ),
746 static_cast< sal_Int32 >( rRelPos.Secondary * rPageSize.Height ));
747
749 aResult, aLegendSize, rRelPos.Anchor );
750
751 // adapt rRemainingSpace if LegendPosition is not CUSTOM
752 // #i109336# Improve auto positioning in chart
753 sal_Int32 nXDistance = lcl_getLegendLeftRightMargin();
754 sal_Int32 nYDistance = lcl_getLegendTopBottomMargin();
755 if (!bOverlay) switch( ePos )
756 {
757 case LegendPosition_LINE_START:
758 {
759 sal_Int32 nExtent = aLegendSize.Width;
760 rRemainingSpace.Width -= ( nExtent + nXDistance );
761 rRemainingSpace.X += ( nExtent + nXDistance );
762 }
763 break;
764 case LegendPosition_LINE_END:
765 {
766 rRemainingSpace.Width -= ( aLegendSize.Width + nXDistance );
767 }
768 break;
769 case LegendPosition_PAGE_START:
770 {
771 sal_Int32 nExtent = aLegendSize.Height;
772 rRemainingSpace.Height -= ( nExtent + nYDistance );
773 rRemainingSpace.Y += ( nExtent + nYDistance );
774 }
775 break;
776 case LegendPosition_PAGE_END:
777 {
778 rRemainingSpace.Height -= ( aLegendSize.Height + nYDistance );
779 }
780 break;
781
782 default:
783 // nothing
784 break;
785 }
786
787 // adjust the legend position. Esp. for old files that had slightly smaller legends
788 const sal_Int32 nEdgeDistance( 30 );
789 if( aResult.X + aLegendSize.Width > rPageSize.Width )
790 {
791 sal_Int32 nNewX( (rPageSize.Width - aLegendSize.Width) - nEdgeDistance );
792 if( nNewX > rPageSize.Width / 4 )
793 aResult.X = nNewX;
794 }
795 if( aResult.Y + aLegendSize.Height > rPageSize.Height )
796 {
797 sal_Int32 nNewY( (rPageSize.Height - aLegendSize.Height) - nEdgeDistance );
798 if( nNewY > rPageSize.Height / 4 )
799 aResult.Y = nNewY;
800 }
801
802 return aResult;
803}
804
805bool lcl_shouldSymbolsBePlacedOnTheLeftSide( const Reference< beans::XPropertySet >& xLegendProp, sal_Int16 nDefaultWritingMode )
806{
807 bool bSymbolsLeftSide = true;
808 try
809 {
811 {
812 if(xLegendProp.is())
813 {
814 sal_Int16 nWritingMode=-1;
815 if( xLegendProp->getPropertyValue( "WritingMode" ) >>= nWritingMode )
816 {
817 if( nWritingMode == text::WritingMode2::PAGE )
818 nWritingMode = nDefaultWritingMode;
819 if( nWritingMode == text::WritingMode2::RL_TB )
820 bSymbolsLeftSide=false;
821 }
822 }
823 }
824 }
825 catch( const uno::Exception & )
826 {
827 DBG_UNHANDLED_EXCEPTION("chart2");
828 }
829 return bSymbolsLeftSide;
830}
831
832std::vector<std::shared_ptr<VButton>> lcl_createButtons(
833 rtl::Reference<SvxShapeGroupAnyD> const & xLegendContainer,
834 ChartModel& rModel, bool bPlaceButtonsVertically, tools::Long & nUsedHeight)
835{
836 std::vector<std::shared_ptr<VButton>> aButtons;
837
838 uno::Reference<chart2::data::XPivotTableDataProvider> xPivotTableDataProvider(rModel.getDataProvider(), uno::UNO_QUERY);
839 if (!xPivotTableDataProvider.is())
840 return aButtons;
841
842 if (!xPivotTableDataProvider->getColumnFields().hasElements())
843 return aButtons;
844
845 awt::Size aSize(2000, 700);
846 int x = 100;
847 int y = 100;
848
849 const css::uno::Sequence<chart2::data::PivotTableFieldEntry> aPivotFieldEntries = xPivotTableDataProvider->getColumnFields();
850 for (chart2::data::PivotTableFieldEntry const & sColumnFieldEntry : aPivotFieldEntries)
851 {
852 auto pButton = std::make_shared<VButton>();
853 aButtons.push_back(pButton);
854 pButton->init(xLegendContainer);
855 awt::Point aNewPosition(x, y);
856 pButton->setLabel(sColumnFieldEntry.Name);
857 pButton->setCID("FieldButton.Column." + OUString::number(sColumnFieldEntry.DimensionIndex));
858 pButton->setPosition(aNewPosition);
859 pButton->setSize(aSize);
860 if (sColumnFieldEntry.Name == "Data")
861 {
862 pButton->showArrow(false);
863 pButton->setBGColor(Color(0x00F6F6F6));
864 }
865 if (sColumnFieldEntry.HasHiddenMembers)
866 pButton->setArrowColor(Color(0x0000FF));
867
868 if (bPlaceButtonsVertically)
869 y += aSize.Height + 100;
870 else
871 x += aSize.Width + 100;
872 }
873 if (bPlaceButtonsVertically)
874 nUsedHeight += y + 100;
875 else
876 nUsedHeight += aSize.Height + 100;
877
878 return aButtons;
879}
880
881} // anonymous namespace
882
886 std::vector< LegendEntryProvider* >&& rLegendEntryProviderList,
888 ChartModel& rModel )
889 : m_xTarget(std::move(xTargetPage))
890 , m_xLegend(std::move(xLegend))
891 , mrModel(rModel)
892 , m_xContext(xContext)
893 , m_aLegendEntryProviderList(std::move(rLegendEntryProviderList))
894 , m_nDefaultWritingMode(text::WritingMode2::LR_TB)
895{
896}
897
898void VLegend::setDefaultWritingMode( sal_Int16 nDefaultWritingMode )
899{
900 m_nDefaultWritingMode = nDefaultWritingMode;
901}
902
904{
905 if( ! xLegend.is())
906 return false;
907
908 bool bShow = false;
909 try
910 {
911 xLegend->getPropertyValue( "Show") >>= bShow;
912 }
913 catch( const uno::Exception & )
914 {
915 DBG_UNHANDLED_EXCEPTION("chart2");
916 }
917
918 return bShow;
919}
920
922 const awt::Size & rAvailableSpace,
923 const awt::Size & rPageSize,
924 awt::Size & rDefaultLegendSize )
925{
926 if(! (m_xLegend.is() && m_xTarget.is()))
927 return;
928
929 try
930 {
931 //create shape and add to page
932 OUString aLegendParticle( ObjectIdentifier::createParticleForLegend( &mrModel ) );
935
936 // create and insert sub-shapes
938 if( xLegendContainer.is() )
939 {
940 // for quickly setting properties
941 tPropertyValues aLineFillProperties;
942 tPropertyValues aTextProperties;
943
944 css::chart::ChartLegendExpansion eExpansion = css::chart::ChartLegendExpansion_HIGH;
945 awt::Size aLegendSize( rAvailableSpace );
946
947 bool bCustom = false;
948 LegendPosition eLegendPosition = LegendPosition_LINE_END;
949 // get Expansion property
950 m_xLegend->getPropertyValue("Expansion") >>= eExpansion;
951 if( eExpansion == css::chart::ChartLegendExpansion_CUSTOM )
952 {
953 RelativeSize aRelativeSize;
954 if (m_xLegend->getPropertyValue("RelativeSize") >>= aRelativeSize)
955 {
956 aLegendSize.Width = static_cast<sal_Int32>(::rtl::math::approxCeil( aRelativeSize.Primary * rPageSize.Width ));
957 aLegendSize.Height = static_cast<sal_Int32>(::rtl::math::approxCeil( aRelativeSize.Secondary * rPageSize.Height ));
958 bCustom = true;
959 }
960 else
961 {
962 eExpansion = css::chart::ChartLegendExpansion_HIGH;
963 }
964 }
965 m_xLegend->getPropertyValue("AnchorPosition") >>= eLegendPosition;
966 lcl_getProperties( m_xLegend, aLineFillProperties, aTextProperties, rPageSize );
967
968 // create entries
969 double fViewFontSize = lcl_CalcViewFontSize( m_xLegend, rPageSize );//todo
970 // #i109336# Improve auto positioning in chart
971 sal_Int32 nSymbolHeight = static_cast< sal_Int32 >( fViewFontSize * 0.6 );
972 sal_Int32 nSymbolWidth = nSymbolHeight;
973
974 for (LegendEntryProvider* pLegendEntryProvider : m_aLegendEntryProviderList)
975 {
976 if (pLegendEntryProvider)
977 {
978 awt::Size aCurrentRatio = pLegendEntryProvider->getPreferredLegendKeyAspectRatio();
979 sal_Int32 nCurrentWidth = aCurrentRatio.Width;
980 if( aCurrentRatio.Height > 0 )
981 {
982 nCurrentWidth = nSymbolHeight* aCurrentRatio.Width/aCurrentRatio.Height;
983 }
984 nSymbolWidth = std::max( nSymbolWidth, nCurrentWidth );
985 }
986 }
987 awt::Size aMaxSymbolExtent( nSymbolWidth, nSymbolHeight );
988
989 std::vector<ViewLegendEntry> aViewEntries;
990 for(LegendEntryProvider* pLegendEntryProvider : m_aLegendEntryProviderList)
991 {
992 if (pLegendEntryProvider)
993 {
994 std::vector<ViewLegendEntry> aNewEntries = pLegendEntryProvider->createLegendEntries(
995 aMaxSymbolExtent, eLegendPosition, m_xLegend,
996 xLegendContainer, m_xContext, mrModel);
997 aViewEntries.insert( aViewEntries.end(), aNewEntries.begin(), aNewEntries.end() );
998 }
999 }
1000
1001 bool bSymbolsLeftSide = lcl_shouldSymbolsBePlacedOnTheLeftSide( m_xLegend, m_nDefaultWritingMode );
1002
1003 uno::Reference<chart2::data::XPivotTableDataProvider> xPivotTableDataProvider( mrModel.getDataProvider(), uno::UNO_QUERY );
1004 bool bIsPivotChart = xPivotTableDataProvider.is();
1005
1006 if ( !aViewEntries.empty() || bIsPivotChart )
1007 {
1008 // create buttons
1009 tools::Long nUsedButtonHeight = 0;
1010 bool bPlaceButtonsVertically = (eLegendPosition != LegendPosition_PAGE_START &&
1011 eLegendPosition != LegendPosition_PAGE_END &&
1012 eExpansion != css::chart::ChartLegendExpansion_WIDE);
1013
1014 std::vector<std::shared_ptr<VButton>> aButtons = lcl_createButtons(xLegendContainer, mrModel, bPlaceButtonsVertically, nUsedButtonHeight);
1015
1016 // A custom size includes the size we used for buttons already, so we need to
1017 // subtract that from the size that is available for the legend
1018 if (bCustom)
1019 aLegendSize.Height -= nUsedButtonHeight;
1020
1021 // place the legend entries
1022 aLegendSize = lcl_placeLegendEntries(aViewEntries, eExpansion, bSymbolsLeftSide, fViewFontSize,
1023 aMaxSymbolExtent, aTextProperties, xLegendContainer,
1024 aLegendSize, nUsedButtonHeight, rPageSize, bIsPivotChart, rDefaultLegendSize);
1025
1026 uno::Reference<beans::XPropertySet> xModelPage(mrModel.getPageBackground());
1027
1028 for (std::shared_ptr<VButton> const & pButton : aButtons)
1029 {
1030 // adjust the width of the buttons if we place them vertically
1031 if (bPlaceButtonsVertically)
1032 pButton->setSize({aLegendSize.Width - 200, pButton->getSize().Height});
1033
1034 // create the buttons
1035 pButton->createShapes(xModelPage);
1036 }
1037
1039 xLegendContainer, aLegendSize, awt::Point(0, 0), aLineFillProperties.first,
1040 aLineFillProperties.second, ShapeFactory::StackPosition::Bottom);
1041
1042 //because of this name this border will be used for marking the legend
1043 ShapeFactory::setShapeName(xBorder, "MarkHandles");
1044 }
1045 }
1046 }
1047 catch( const uno::Exception & )
1048 {
1049 DBG_UNHANDLED_EXCEPTION("chart2" );
1050 }
1051}
1052
1054 awt::Rectangle & rOutAvailableSpace,
1055 const awt::Size & rPageSize,
1056 const css::awt::Size & rDefaultLegendSize )
1057{
1058 if(! m_xShape.is())
1059 return;
1060
1061 try
1062 {
1063 // determine position and alignment depending on default position
1064 awt::Size aLegendSize = m_xShape->getSize();
1065 chart2::RelativePosition aRelativePosition;
1066
1067 bool bDefaultLegendSize = rDefaultLegendSize.Width != 0 || rDefaultLegendSize.Height != 0;
1068 bool bAutoPosition =
1069 ! (m_xLegend->getPropertyValue( "RelativePosition") >>= aRelativePosition);
1070
1071 LegendPosition ePos = LegendPosition_LINE_END;
1072 m_xLegend->getPropertyValue( "AnchorPosition") >>= ePos;
1073
1074 bool bOverlay = false;
1075 m_xLegend->getPropertyValue("Overlay") >>= bOverlay;
1076 //calculate position
1077 if( bAutoPosition )
1078 {
1079 // auto position: relative to remaining space
1080 aRelativePosition = lcl_getDefaultPosition( ePos, rOutAvailableSpace, rPageSize );
1081 awt::Point aPos = lcl_calculatePositionAndRemainingSpace(
1082 rOutAvailableSpace, rPageSize, aRelativePosition, ePos, aLegendSize, bOverlay );
1083 m_xShape->setPosition( aPos );
1084 }
1085 else
1086 {
1087 // manual position: relative to whole page
1088 awt::Rectangle aAvailableSpace( 0, 0, rPageSize.Width, rPageSize.Height );
1089 awt::Point aPos = lcl_calculatePositionAndRemainingSpace(
1090 aAvailableSpace, rPageSize, aRelativePosition, ePos, bDefaultLegendSize ? rDefaultLegendSize : aLegendSize, bOverlay );
1091 m_xShape->setPosition( aPos );
1092
1093 if (!bOverlay)
1094 {
1095 // calculate remaining space as if having autoposition:
1096 aRelativePosition = lcl_getDefaultPosition( ePos, rOutAvailableSpace, rPageSize );
1097 lcl_calculatePositionAndRemainingSpace(
1098 rOutAvailableSpace, rPageSize, aRelativePosition, ePos, bDefaultLegendSize ? rDefaultLegendSize : aLegendSize, bOverlay );
1099 }
1100 }
1101 }
1102 catch( const uno::Exception & )
1103 {
1104 DBG_UNHANDLED_EXCEPTION("chart2" );
1105 }
1106}
1107
1108} //namespace chart
1109
1110/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
css::chart::ChartAxisLabelPosition ePos
ChartModel & mrModel
Reference< uno::XComponentContext > m_xContext
constexpr auto convertPointToMm100(N n)
static bool IsCTLFontEnabled()
static bool removeShape(const rtl::Reference< SvxShape > &xShape)
static OUString createClassifiedIdentifierForParticle(std::u16string_view rParticle)
static OUString createParticleForLegend(const rtl::Reference<::chart::ChartModel > &xChartModel)
static const tPropertyNameMap & getPropertyNameMapForFillAndLineProperties()
static css::uno::Any * getValuePointer(tAnySequence &rPropValues, const tNameSequence &rPropNames, std::u16string_view rPropName)
static const tPropertyNameMap & getPropertyNameMapForCharacterProperties()
static void getMultiPropertyListsFromValueMap(tNameSequence &rNames, tAnySequence &rValues, const tPropertyNameValueMap &rValueMap)
static void getValueMap(tPropertyNameValueMap &rValueMap, const tPropertyNameMap &rNameMap, const css::uno::Reference< css::beans::XPropertySet > &xSourceProp)
Fetch property values from the source object and map it to the destination container.
static css::awt::Point getUpperLeftCornerOfAnchoredObject(css::awt::Point aPoint, css::awt::Size aObjectSize, css::drawing::Alignment aAnchor)
returns the upper left corner of an object that has size aObjectSize and where the point indicated by...
static double calculate(double fValue, const css::awt::Size &rOldReferenceSize, const css::awt::Size &rNewReferenceSize)
static void setShapeName(const rtl::Reference< SvxShape > &xShape, const OUString &rName)
static rtl::Reference< SvxShapeRect > createRectangle(const rtl::Reference< SvxShapeGroupAnyD > &xTarget, const css::awt::Size &rSize, const css::awt::Point &rPosition, const tNameSequence &rPropNames, const tAnySequence &rPropValues, StackPosition ePos=StackPosition::Top)
static rtl::Reference< SvxShapeText > createText(const rtl::Reference< SvxShapeGroupAnyD > &xTarget2D, const OUString &rText, const tNameSequence &rPropNames, const tAnySequence &rPropValues, const css::uno::Any &rATransformation)
static rtl::Reference< SvxShapeGroup > createGroup2D(const rtl::Reference< SvxShapeGroupAnyD > &xTarget, const OUString &aName=OUString())
void setDefaultWritingMode(sal_Int16 nDefaultWritingMode)
Definition: VLegend.cxx:898
css::uno::Reference< css::uno::XComponentContext > m_xContext
Definition: VLegend.hxx:82
rtl::Reference<::chart::Legend > m_xLegend
Definition: VLegend.hxx:77
void createShapes(const css::awt::Size &rAvailableSpace, const css::awt::Size &rPageSize, css::awt::Size &rDefaultLegendSize)
Definition: VLegend.cxx:921
std::vector< LegendEntryProvider * > m_aLegendEntryProviderList
Definition: VLegend.hxx:84
VLegend(rtl::Reference< ::chart::Legend > xLegend, const css::uno::Reference< css::uno::XComponentContext > &xContext, std::vector< LegendEntryProvider * > &&rLegendEntryProviderList, rtl::Reference< SvxShapeGroupAnyD > xTargetPage, ChartModel &rModel)
Definition: VLegend.cxx:883
ChartModel & mrModel
Definition: VLegend.hxx:80
sal_Int16 m_nDefaultWritingMode
Definition: VLegend.hxx:86
rtl::Reference< SvxShapeGroup > m_xShape
Definition: VLegend.hxx:78
static bool isVisible(const rtl::Reference< ::chart::Legend > &xLegend)
Definition: VLegend.cxx:903
rtl::Reference< SvxShapeGroupAnyD > m_xTarget
Definition: VLegend.hxx:76
void changePosition(css::awt::Rectangle &rOutAvailableSpace, const css::awt::Size &rReferenceSize, const css::awt::Size &rDefaultLegendSize)
Sets the position according to its internal anchor.
Definition: VLegend.cxx:1053
Reference< lang::XComponent > m_xTarget
#define DBG_UNHANDLED_EXCEPTION(...)
float u
float y
float x
sal_Int32 nIndex
def text(shape, orig_st)
std::unordered_map< OUString, css::uno::Any > tPropertyNameValueMap
long Long