LibreOffice Module oox (master)  1
titleconverter.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 
21 
22 #include <com/sun/star/chart/ChartLegendExpansion.hpp>
23 #include <com/sun/star/chart2/FormattedString.hpp>
24 #include <com/sun/star/chart2/LegendPosition.hpp>
25 #include <com/sun/star/chart2/XDiagram.hpp>
26 #include <com/sun/star/chart2/XLegend.hpp>
27 #include <com/sun/star/chart2/XTitle.hpp>
28 #include <com/sun/star/chart2/XTitled.hpp>
29 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
30 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
31 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
32 
33 #include <comphelper/sequence.hxx>
34 #include <osl/diagnose.h>
35 #include <drawingml/textbody.hxx>
39 #include <oox/token/properties.hxx>
40 #include <oox/token/tokens.hxx>
41 #include <com/sun/star/chart2/RelativePosition.hpp>
42 #include <com/sun/star/drawing/Alignment.hpp>
43 
45 namespace oox::drawingml::chart {
46 
47 using namespace ::com::sun::star::awt;
48 using namespace ::com::sun::star::chart2;
49 using namespace ::com::sun::star::chart2::data;
50 using namespace ::com::sun::star::drawing;
51 using namespace ::com::sun::star::uno;
52 
53 
55  ConverterBase< TextModel >( rParent, rModel )
56 {
57 }
58 
60 {
61 }
62 
64 {
66  if( mrModel.mxDataSeq.is() )
67  {
68  DataSequenceConverter aDataSeqConv( *this, *mrModel.mxDataSeq );
69  xDataSeq = aDataSeqConv.createDataSequence( rRole );
70  }
71  return xDataSeq;
72 }
73 
75  const OUString& rDefaultText, const ModelRef< TextBody >& rxTextProp, ObjectType eObjType )
76 {
77  OSL_ENSURE( !mrModel.mxDataSeq || !mrModel.mxTextBody, "TextConverter::createStringSequence - linked string and rich text found" );
78  ::std::vector< Reference< XFormattedString > > aStringVec;
79  if( mrModel.mxTextBody.is() )
80  {
81  // rich-formatted text objects can be created, but currently Chart2 is not able to show them
82  const TextParagraphVector& rTextParas = mrModel.mxTextBody->getParagraphs();
83  for( TextParagraphVector::const_iterator aPIt = rTextParas.begin(), aPEnd = rTextParas.end(); aPIt != aPEnd; ++aPIt )
84  {
85  const TextParagraph& rTextPara = **aPIt;
86  const TextCharacterProperties& rParaProps = rTextPara.getProperties().getTextCharacterProperties();
87  for( TextRunVector::const_iterator aRIt = rTextPara.getRuns().begin(), aREnd = rTextPara.getRuns().end(); aRIt != aREnd; ++aRIt )
88  {
89  const TextRun& rTextRun = **aRIt;
90  bool bAddNewLine = ((aRIt + 1 == aREnd) && (aPIt + 1 != aPEnd)) || rTextRun.isLineBreak();
91  Reference< XFormattedString > xFmtStr = appendFormattedString( aStringVec, rTextRun.getText(), bAddNewLine );
92  PropertySet aPropSet( xFmtStr );
93  TextCharacterProperties aRunProps( rParaProps );
94  aRunProps.assignUsed( rTextRun.getTextCharacterProperties() );
95  getFormatter().convertTextFormatting( aPropSet, aRunProps, eObjType );
96  }
97  }
98  }
99  else
100  {
101  OUString aString;
102  // try to create string from linked data
103  if( mrModel.mxDataSeq.is() && !mrModel.mxDataSeq->maData.empty() )
104  mrModel.mxDataSeq->maData.begin()->second >>= aString;
105  // no linked string -> fall back to default string
106  if( aString.isEmpty() )
107  aString = rDefaultText;
108 
109  // create formatted string object
110  if( !aString.isEmpty() )
111  {
112  Reference< XFormattedString > xFmtStr = appendFormattedString( aStringVec, aString, false );
113  PropertySet aPropSet( xFmtStr );
114  getFormatter().convertTextFormatting( aPropSet, rxTextProp, eObjType );
115  }
116  }
117 
118  return comphelper::containerToSequence( aStringVec );
119 }
120 
122  ::std::vector< Reference< XFormattedString > >& orStringVec, const OUString& rString, bool bAddNewLine ) const
123 {
125  try
126  {
127  xFmtStr = FormattedString::create( ConverterRoot::getComponentContext() );
128  xFmtStr->setString( bAddNewLine ? (rString + "\n") : rString );
129  orStringVec.emplace_back(xFmtStr );
130  }
131  catch( Exception& )
132  {
133  }
134  return xFmtStr;
135 }
136 
138  ConverterBase< TitleModel >( rParent, rModel )
139 {
140 }
141 
143 {
144 }
145 
146 void TitleConverter::convertFromModel( const Reference< XTitled >& rxTitled, const OUString& rAutoTitle, ObjectType eObjType, sal_Int32 nMainIdx, sal_Int32 nSubIdx )
147 {
148  if( !rxTitled.is() )
149  return;
150 
151  // create the formatted strings
152  TextModel& rText = mrModel.mxText.getOrCreate();
153  TextConverter aTextConv( *this, rText );
154  Sequence< Reference< XFormattedString > > aStringSeq = aTextConv.createStringSequence( rAutoTitle, mrModel.mxTextProp, eObjType );
155  if( !aStringSeq.hasElements() )
156  return;
157 
158  try
159  {
160  // create the title object and set the string data
161  Reference< XTitle > xTitle( createInstance( "com.sun.star.chart2.Title" ), UNO_QUERY_THROW );
162  xTitle->setText( aStringSeq );
163  rxTitled->setTitleObject( xTitle );
164 
165  // frame formatting (text formatting already done in TextConverter::createStringSequence())
166  PropertySet aPropSet( xTitle );
167  getFormatter().convertFrameFormatting( aPropSet, mrModel.mxShapeProp, eObjType );
168 
169  // frame rotation
170  OSL_ENSURE( !mrModel.mxTextProp || !rText.mxTextBody, "TitleConverter::convertFromModel - multiple text properties" );
172  ObjectFormatter::convertTextRotation( aPropSet, xTextProp, true, mrModel.mnDefaultRotation );
173 
174  // register the title and layout data for conversion of position
175  registerTitleLayout( xTitle, mrModel.mxLayout, eObjType, nMainIdx, nSubIdx );
176  }
177  catch( Exception& )
178  {
179  }
180 }
181 
183  ConverterBase< LegendModel >( rParent, rModel )
184 {
185 }
186 
188 {
189 }
190 
192 {
193  if( !rxDiagram.is() )
194  return;
195 
196  try
197  {
198  namespace cssc = ::com::sun::star::chart;
199  namespace cssc2 = ::com::sun::star::chart2;
200 
201  // create the legend
202  Reference< XLegend > xLegend( createInstance( "com.sun.star.chart2.Legend" ), UNO_QUERY_THROW );
203  rxDiagram->setLegend( xLegend );
204  PropertySet aPropSet( xLegend );
205  aPropSet.setProperty( PROP_Show, true );
206 
207  // legend formatting
209 
210  // predefined legend position and expansion
211  cssc2::LegendPosition eLegendPos = cssc2::LegendPosition_LINE_END;
212  cssc::ChartLegendExpansion eLegendExpand = cssc::ChartLegendExpansion_CUSTOM;
213  RelativePosition eRelPos;
214  bool bTopRight=false;
215  switch( mrModel.mnPosition )
216  {
217  case XML_l:
218  eLegendPos = cssc2::LegendPosition_LINE_START;
219  eLegendExpand = cssc::ChartLegendExpansion_HIGH;
220  break;
221  case XML_r:
222  eLegendPos = cssc2::LegendPosition_LINE_END;
223  eLegendExpand = cssc::ChartLegendExpansion_HIGH;
224  break;
225  case XML_tr: // top-right not supported
226  eRelPos.Primary = 1;
227  eRelPos.Secondary =0;
228  eRelPos.Anchor = Alignment_TOP_RIGHT;
229  bTopRight=true;
230  break;
231  case XML_t:
232  eLegendPos = cssc2::LegendPosition_PAGE_START;
233  eLegendExpand = cssc::ChartLegendExpansion_WIDE;
234  break;
235  case XML_b:
236  eLegendPos = cssc2::LegendPosition_PAGE_END;
237  eLegendExpand = cssc::ChartLegendExpansion_WIDE;
238  break;
239  }
240  bool bManualLayout=false;
241  // manual positioning and size
242  if( mrModel.mxLayout )
243  {
244  LayoutConverter aLayoutConv( *this, *mrModel.mxLayout );
245  // manual size needs ChartLegendExpansion_CUSTOM
246  if( aLayoutConv.convertFromModel( aPropSet ) )
247  {
248  eLegendExpand = cssc::ChartLegendExpansion_CUSTOM;
249  }
250  bManualLayout = !aLayoutConv.getAutoLayout();
251  }
252 
253  // set position and expansion properties
254  aPropSet.setProperty( PROP_AnchorPosition, eLegendPos );
255  aPropSet.setProperty( PROP_Expansion, eLegendExpand );
256 
257  if (bTopRight && !bManualLayout)
258  aPropSet.setProperty( PROP_RelativePosition , Any(eRelPos));
259 
260  aPropSet.setProperty(PROP_Overlay, mrModel.mbOverlay);
261 
262  if (mrModel.maLegendEntries.size() > 0)
263  legendEntriesFormatting(rxDiagram);
264  }
265  catch( Exception& )
266  {
267  }
268 }
269 
271 {
272  Reference<XCoordinateSystemContainer> xCooSysContainer(rxDiagram, UNO_QUERY_THROW);
273  const Sequence<Reference<XCoordinateSystem>> xCooSysSequence(xCooSysContainer->getCoordinateSystems());
274  if (!xCooSysSequence.hasElements())
275  return;
276 
277  sal_Int32 nIndex = 0;
278  for (const auto& rCooSys : xCooSysSequence)
279  {
280  PropertySet aCooSysProp(rCooSys);
281  bool bSwapXAndY = aCooSysProp.getBoolProperty(PROP_SwapXAndYAxis);
282 
283  Reference<XChartTypeContainer> xChartTypeContainer(rCooSys, UNO_QUERY_THROW);
284  const Sequence<Reference<XChartType>> xChartTypeSequence(xChartTypeContainer->getChartTypes());
285  if (!xChartTypeSequence.hasElements())
286  continue;
287 
288  for (const auto& rCT : xChartTypeSequence)
289  {
290  Reference<XDataSeriesContainer> xDSCont(rCT, UNO_QUERY);
291  if (!xDSCont.is())
292  continue;
293 
294  bool bIsPie
295  = rCT->getChartType().equalsIgnoreAsciiCase("com.sun.star.chart2.PieChartType");
296  if (bIsPie)
297  {
298  PropertySet xChartTypeProp(rCT);
299  bIsPie = !xChartTypeProp.getBoolProperty(PROP_UseRings);
300  }
301  const Sequence<Reference<XDataSeries>> aDataSeriesSeq = xDSCont->getDataSeries();
302  if (bSwapXAndY)
303  nIndex += aDataSeriesSeq.getLength() - 1;
304  for (const auto& rDataSeries : aDataSeriesSeq)
305  {
306  PropertySet aSeriesProp(rDataSeries);
307  bool bVaryColorsByPoint = aSeriesProp.getBoolProperty(PROP_VaryColorsByPoint);
308 
309  if (bVaryColorsByPoint || bIsPie)
310  {
311  Reference<XDataSource> xDSrc(rDataSeries, UNO_QUERY);
312  if (!xDSrc.is())
313  continue;
314 
315  const Sequence<Reference<XLabeledDataSequence> > aDataSeqs = xDSrc->getDataSequences();
316  std::vector<sal_Int32> deletedLegendEntries;
317  sal_Int32 j = 0;
318  for (const auto& rDataSeq : aDataSeqs)
319  {
320  Reference<XDataSequence> xValues = rDataSeq->getValues();
321  if (!xValues.is())
322  continue;
323 
324  sal_Int32 nDataSeqSize = xValues->getData().getLength();
325  for (sal_Int32 i = 0; i < nDataSeqSize; ++i)
326  {
327  for (const auto& rLegendEntry : mrModel.maLegendEntries)
328  {
329  if (nIndex == rLegendEntry->mnLegendEntryIdx && rLegendEntry->mbLabelDeleted)
330  {
331  deletedLegendEntries.push_back(j + i);
332  break;
333  }
334  }
335  nIndex++;
336  }
337  j += nDataSeqSize;
338  }
339  if (deletedLegendEntries.size() > 0)
340  aSeriesProp.setProperty(PROP_DeletedLegendEntries, comphelper::containerToSequence(deletedLegendEntries));
341  }
342  else
343  {
344  for (const auto& rLegendEntry : mrModel.maLegendEntries)
345  {
346  if (nIndex == rLegendEntry->mnLegendEntryIdx)
347  {
348  aSeriesProp.setProperty(PROP_ShowLegendEntry, !rLegendEntry->mbLabelDeleted);
349  break;
350  }
351  }
352  bSwapXAndY ? nIndex-- : nIndex++;
353  }
354  }
355  if (bSwapXAndY)
356  nIndex += aDataSeriesSeq.getLength() + 1;
357  }
358  }
359 }
360 
361 } // namespace oox::drawingml::chart
362 
363 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
LayoutRef mxLayout
Legend text formatting.
Definition: titlemodel.hxx:76
sal_Int32 nIndex
TextRef mxText
Layout/position of the frame.
Definition: titlemodel.hxx:50
bool mbOverlay
Legend position.
Definition: titlemodel.hxx:78
css::uno::Reference< css::chart2::XFormattedString > appendFormattedString(::std::vector< css::uno::Reference< css::chart2::XFormattedString > > &orStringVec, const OUString &rString, bool bAddNewLine) const
void convertTextFormatting(PropertySet &rPropSet, const ModelRef< TextBody > &rxTextProp, ObjectType eObjType)
Sets text formatting properties to the passed property set.
Base class of all converter classes.
TextBodyRef mxTextProp
Legend shape formatting.
Definition: titlemodel.hxx:75
css::uno::Reference< css::chart2::data::XDataSequence > createDataSequence(const OUString &rRole)
Creates a data sequence object from the contained text data.
TextBodyRef mxTextProp
Title shape formatting.
Definition: titlemodel.hxx:48
void convertFromModel(const css::uno::Reference< css::chart2::XDiagram > &rxDiagram)
Creates a legend object and attaches it at the passed diagram.
TextConverter(const ConverterRoot &rParent, TextModel &rModel)
void registerTitleLayout(const css::uno::Reference< css::chart2::XTitle > &rxTitle, const ModelRef< LayoutModel > &rxLayout, ObjectType eObjType, sal_Int32 nMainIdx, sal_Int32 nSubIdx)
Registers a title object and its layout data, needed for conversion of the title position using the o...
css::uno::Reference< css::uno::XInterface > createInstance(const OUString &rServiceName) const
Creates an instance for the passed service name, using the process service factory.
ObjectType
Enumerates different object types for specific automatic formatting behaviour.
LegendConverter(const ConverterRoot &rParent, LegendModel &rModel)
void convertFrameFormatting(PropertySet &rPropSet, const ModelRef< Shape > &rxShapeProp, ObjectType eObjType, sal_Int32 nSeriesIdx=-1)
Sets frame formatting properties to the passed property set.
ShapeRef mxShapeProp
Legend entries formatting.
Definition: titlemodel.hxx:74
css::uno::Sequence< css::uno::Reference< css::chart2::XFormattedString > > createStringSequence(const OUString &rDefaultText, const ModelRef< TextBody > &rxTextProp, ObjectType eObjType)
Creates a sequence of formatted string objects.
void convertFormatting(PropertySet &rPropSet, const ModelRef< Shape > &rxShapeProp, const ModelRef< TextBody > &rxTextProp, ObjectType eObjType)
Sets frame/text formatting properties to the passed property set.
sal_Int32 mnPosition
Layout/position of the legend.
Definition: titlemodel.hxx:77
void legendEntriesFormatting(const css::uno::Reference< css::chart2::XDiagram > &rxDiagram)
TextCharacterProperties & getTextCharacterProperties()
Definition: textrun.hxx:40
css::uno::Reference< css::uno::XComponentContext > const & getComponentContext() const
A wrapper for a UNO property set.
Definition: propertyset.hxx:57
TitleConverter(const ConverterRoot &rParent, TitleModel &rModel)
static void convertTextRotation(PropertySet &rPropSet, const ModelRef< TextBody > &rxTextProp, bool bSupportsStacked, sal_Int32 nDefaultRotation=0)
Sets text rotation properties to the passed property set.
A layout converter calculates positions and sizes for various chart objects.
bool getBoolProperty(sal_Int32 nPropId) const
Gets the specified boolean property from the property set.
Definition: propertyset.hxx:99
sal_Int32 mnDefaultRotation
True = title may overlay other objects.
Definition: titlemodel.hxx:52
css::uno::Reference< css::chart2::data::XDataSequence > createDataSequence(const OUString &rRole)
Creates a data sequence object from the contained formula link.
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
LayoutRef mxLayout
Title text formatting.
Definition: titlemodel.hxx:49
OUString & getText()
Definition: textrun.hxx:37
void assignUsed(const TextCharacterProperties &rSourceProps)
Overwrites all members that are explicitly set in rSourceProps.
bool isLineBreak() const
Definition: textrun.hxx:44
void convertFromModel(const css::uno::Reference< css::chart2::XTitled > &rxTitled, const OUString &rAutoTitle, ObjectType eObjType, sal_Int32 nMainIdx=-1, sal_Int32 nSubIdx=-1)
Creates a title text object and attaches it at the passed interface.
TextCharacterProperties & getTextCharacterProperties()
TextParagraphProperties & getProperties()
TextBodyRef mxTextBody
The string data or formula link of this text.
Definition: titlemodel.hxx:34
bool convertFromModel(PropertySet &rPropSet)
Tries to set the position and size from the contained OOXML layout model.
bool setProperty(sal_Int32 nPropId, const Type &rValue)
Puts the passed value into the property set.
ObjectFormatter & getFormatter() const
Returns the object formatter.