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