tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / oox / source / drawingml / chart / titleconverter.cxx
blob0ee8affc7984d015c153d7f7c4b48826b3e14f20
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <drawingml/chart/titleconverter.hxx>
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>
33 #include <comphelper/sequence.hxx>
34 #include <osl/diagnose.h>
35 #include <drawingml/textbody.hxx>
36 #include <drawingml/textparagraph.hxx>
37 #include <drawingml/chart/datasourceconverter.hxx>
38 #include <drawingml/chart/titlemodel.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>
44 #include <oox/drawingml/chart/modelbase.hxx>
45 namespace oox::drawingml::chart {
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;
53 TextConverter::TextConverter( const ConverterRoot& rParent, TextModel& rModel ) :
54 ConverterBase< TextModel >( rParent, rModel )
58 TextConverter::~TextConverter()
62 Reference< XDataSequence > TextConverter::createDataSequence( const OUString& rRole )
64 Reference< XDataSequence > xDataSeq;
65 if( mrModel.mxDataSeq.is() )
67 DataSequenceConverter aDataSeqConv( *this, *mrModel.mxDataSeq );
68 xDataSeq = aDataSeqConv.createDataSequence( rRole );
70 return xDataSeq;
73 Sequence< Reference< XFormattedString > > TextConverter::createStringSequence(
74 const OUString& rDefaultText, const ModelRef< TextBody >& rxTextProp, ObjectType eObjType )
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() )
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 )
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 )
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;
93 if (rParaProps.mbHasEmptyParaProperties && rxTextProp.is() && rxTextProp->hasParagraphProperties())
95 const TextParagraphVector rDefTextParas = rxTextProp->getParagraphs();
96 TextParagraphVector::const_iterator aDefPIt = rDefTextParas.begin();
97 const TextParagraph& rDefTextPara = **aDefPIt;
98 aRunProps = rDefTextPara.getProperties().getTextCharacterProperties();
100 else
101 aRunProps = rParaProps;
102 aRunProps.assignUsed( rTextRun.getTextCharacterProperties() );
103 getFormatter().convertTextFormatting( aPropSet, aRunProps, eObjType );
107 else
109 OUString aString;
110 // try to create string from linked data
111 if( mrModel.mxDataSeq.is() && !mrModel.mxDataSeq->maData.empty() )
112 mrModel.mxDataSeq->maData.begin()->second >>= aString;
113 // no linked string -> fall back to default string
114 if( aString.isEmpty() )
115 aString = rDefaultText;
117 // create formatted string object
118 if( !aString.isEmpty() )
120 Reference< XFormattedString > xFmtStr = appendFormattedString( aStringVec, aString, false );
121 PropertySet aPropSet( xFmtStr );
122 getFormatter().convertTextFormatting( aPropSet, rxTextProp, eObjType );
126 return comphelper::containerToSequence( aStringVec );
129 Reference< XFormattedString > TextConverter::appendFormattedString(
130 ::std::vector< Reference< XFormattedString > >& orStringVec, const OUString& rString, bool bAddNewLine ) const
132 Reference< XFormattedString2 > xFmtStr;
135 xFmtStr = FormattedString::create( ConverterRoot::getComponentContext() );
136 xFmtStr->setString( bAddNewLine ? (rString + "\n") : rString );
137 orStringVec.emplace_back(xFmtStr );
139 catch( Exception& )
142 return xFmtStr;
145 TitleConverter::TitleConverter( const ConverterRoot& rParent, TitleModel& rModel ) :
146 ConverterBase< TitleModel >( rParent, rModel )
150 TitleConverter::~TitleConverter()
154 void TitleConverter::convertFromModel( const Reference< XTitled >& rxTitled, const OUString& rAutoTitle, ObjectType eObjType, sal_Int32 nMainIdx, sal_Int32 nSubIdx )
156 if( !rxTitled.is() )
157 return;
159 // create the formatted strings
160 TextModel& rText = mrModel.mxText.getOrCreate();
161 TextConverter aTextConv( *this, rText );
162 Sequence< Reference< XFormattedString > > aStringSeq = aTextConv.createStringSequence( rAutoTitle, mrModel.mxTextProp, eObjType );
163 if( !aStringSeq.hasElements() )
164 return;
168 // create the title object and set the string data
169 Reference< XTitle > xTitle( createInstance( u"com.sun.star.chart2.Title"_ustr ), UNO_QUERY_THROW );
170 xTitle->setText( aStringSeq );
171 rxTitled->setTitleObject( xTitle );
173 // frame formatting (text formatting already done in TextConverter::createStringSequence())
174 PropertySet aPropSet( xTitle );
175 getFormatter().convertFrameFormatting( aPropSet, mrModel.mxShapeProp, eObjType );
177 // frame rotation
178 OSL_ENSURE( !mrModel.mxTextProp || !rText.mxTextBody, "TitleConverter::convertFromModel - multiple text properties" );
179 ModelRef< TextBody > xTextProp = mrModel.mxTextProp.is() ? mrModel.mxTextProp : rText.mxTextBody;
180 ObjectFormatter::convertTextRotation( aPropSet, xTextProp, true, mrModel.mnDefaultRotation );
182 // register the title and layout data for conversion of position
183 registerTitleLayout( xTitle, mrModel.mxLayout, eObjType, nMainIdx, nSubIdx );
185 catch( Exception& )
190 LegendConverter::LegendConverter( const ConverterRoot& rParent, LegendModel& rModel ) :
191 ConverterBase< LegendModel >( rParent, rModel )
195 LegendConverter::~LegendConverter()
199 void LegendConverter::convertFromModel( const Reference< XDiagram >& rxDiagram )
201 if( !rxDiagram.is() )
202 return;
206 namespace cssc = css::chart;
207 namespace cssc2 = css::chart2;
209 // create the legend
210 Reference< XLegend > xLegend( createInstance( u"com.sun.star.chart2.Legend"_ustr ), UNO_QUERY_THROW );
211 rxDiagram->setLegend( xLegend );
212 PropertySet aPropSet( xLegend );
213 aPropSet.setProperty( PROP_Show, true );
215 // legend formatting
216 getFormatter().convertFormatting( aPropSet, mrModel.mxShapeProp, mrModel.mxTextProp, OBJECTTYPE_LEGEND );
218 // predefined legend position and expansion
219 cssc2::LegendPosition eLegendPos = cssc2::LegendPosition_LINE_END;
220 cssc::ChartLegendExpansion eLegendExpand = cssc::ChartLegendExpansion_CUSTOM;
221 RelativePosition eRelPos;
222 bool bTopRight=false;
223 switch( mrModel.mnPosition )
225 case XML_l:
226 eLegendPos = cssc2::LegendPosition_LINE_START;
227 eLegendExpand = cssc::ChartLegendExpansion_HIGH;
228 break;
229 case XML_r:
230 eLegendPos = cssc2::LegendPosition_LINE_END;
231 eLegendExpand = cssc::ChartLegendExpansion_HIGH;
232 break;
233 case XML_tr: // top-right not supported
234 eRelPos.Primary = 1;
235 eRelPos.Secondary =0;
236 eRelPos.Anchor = Alignment_TOP_RIGHT;
237 bTopRight=true;
238 break;
239 case XML_t:
240 eLegendPos = cssc2::LegendPosition_PAGE_START;
241 eLegendExpand = cssc::ChartLegendExpansion_WIDE;
242 break;
243 case XML_b:
244 eLegendPos = cssc2::LegendPosition_PAGE_END;
245 eLegendExpand = cssc::ChartLegendExpansion_WIDE;
246 break;
248 bool bManualLayout=false;
249 // manual positioning and size
250 if( mrModel.mxLayout )
252 LayoutConverter aLayoutConv( *this, *mrModel.mxLayout );
253 // manual size needs ChartLegendExpansion_CUSTOM
254 if( aLayoutConv.convertFromModel( aPropSet ) )
256 eLegendExpand = cssc::ChartLegendExpansion_CUSTOM;
258 bManualLayout = !aLayoutConv.getAutoLayout();
261 // set position and expansion properties
262 aPropSet.setProperty( PROP_AnchorPosition, eLegendPos );
263 aPropSet.setProperty( PROP_Expansion, eLegendExpand );
265 if (bTopRight && !bManualLayout)
266 aPropSet.setProperty( PROP_RelativePosition , Any(eRelPos));
268 aPropSet.setProperty(PROP_Overlay, mrModel.mbOverlay);
270 if (mrModel.maLegendEntries.size() > 0)
271 legendEntriesFormatting(rxDiagram);
273 catch( Exception& )
278 void LegendConverter::legendEntriesFormatting(const Reference<XDiagram>& rxDiagram)
280 Reference<XCoordinateSystemContainer> xCooSysContainer(rxDiagram, UNO_QUERY_THROW);
281 const Sequence<Reference<XCoordinateSystem>> xCooSysSequence(xCooSysContainer->getCoordinateSystems());
282 if (!xCooSysSequence.hasElements())
283 return;
285 sal_Int32 nIndex = 0;
286 for (const auto& rCooSys : xCooSysSequence)
288 PropertySet aCooSysProp(rCooSys);
289 bool bSwapXAndY = aCooSysProp.getBoolProperty(PROP_SwapXAndYAxis);
291 Reference<XChartTypeContainer> xChartTypeContainer(rCooSys, UNO_QUERY_THROW);
292 const Sequence<Reference<XChartType>> xChartTypeSequence(xChartTypeContainer->getChartTypes());
293 if (!xChartTypeSequence.hasElements())
294 continue;
296 for (const auto& rCT : xChartTypeSequence)
298 Reference<XDataSeriesContainer> xDSCont(rCT, UNO_QUERY);
299 if (!xDSCont.is())
300 continue;
302 bool bIsPie
303 = rCT->getChartType().equalsIgnoreAsciiCase("com.sun.star.chart2.PieChartType");
304 if (bIsPie)
306 PropertySet xChartTypeProp(rCT);
307 bIsPie = !xChartTypeProp.getBoolProperty(PROP_UseRings);
309 const Sequence<Reference<XDataSeries>> aDataSeriesSeq = xDSCont->getDataSeries();
310 if (bSwapXAndY)
311 nIndex += aDataSeriesSeq.getLength() - 1;
312 for (const auto& rDataSeries : aDataSeriesSeq)
314 PropertySet aSeriesProp(rDataSeries);
315 bool bVaryColorsByPoint = aSeriesProp.getBoolProperty(PROP_VaryColorsByPoint);
317 if (bVaryColorsByPoint || bIsPie)
319 Reference<XDataSource> xDSrc(rDataSeries, UNO_QUERY);
320 if (!xDSrc.is())
321 continue;
323 const Sequence<Reference<XLabeledDataSequence> > aDataSeqs = xDSrc->getDataSequences();
324 std::vector<sal_Int32> deletedLegendEntries;
325 sal_Int32 j = 0;
326 for (const auto& rDataSeq : aDataSeqs)
328 Reference<XDataSequence> xValues = rDataSeq->getValues();
329 if (!xValues.is())
330 continue;
332 sal_Int32 nDataSeqSize = xValues->getData().getLength();
333 for (sal_Int32 i = 0; i < nDataSeqSize; ++i)
335 for (const auto& rLegendEntry : mrModel.maLegendEntries)
337 if (nIndex == rLegendEntry->mnLegendEntryIdx && rLegendEntry->mbLabelDeleted)
339 deletedLegendEntries.push_back(j + i);
340 break;
343 nIndex++;
345 j += nDataSeqSize;
347 if (deletedLegendEntries.size() > 0)
348 aSeriesProp.setProperty(PROP_DeletedLegendEntries, comphelper::containerToSequence(deletedLegendEntries));
350 else
352 for (const auto& rLegendEntry : mrModel.maLegendEntries)
354 if (nIndex == rLegendEntry->mnLegendEntryIdx)
356 aSeriesProp.setProperty(PROP_ShowLegendEntry, !rLegendEntry->mbLabelDeleted);
357 break;
360 bSwapXAndY ? nIndex-- : nIndex++;
363 if (bSwapXAndY)
364 nIndex += aDataSeriesSeq.getLength() + 1;
369 } // namespace oox::drawingml::chart
371 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */