1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 #include "oox/drawingml/chart/titleconverter.hxx"
25
26 #include <com/sun/star/chart/ChartLegendExpansion.hpp>
27 #include <com/sun/star/chart2/LegendPosition.hpp>
28 #include <com/sun/star/chart2/XDiagram.hpp>
29 #include <com/sun/star/chart2/XFormattedString.hpp>
30 #include <com/sun/star/chart2/XLegend.hpp>
31 #include <com/sun/star/chart2/XTitle.hpp>
32 #include <com/sun/star/chart2/XTitled.hpp>
33 #include "oox/drawingml/textbody.hxx"
34 #include "oox/drawingml/textparagraph.hxx"
35 #include "oox/drawingml/chart/datasourceconverter.hxx"
36 #include "oox/drawingml/chart/titlemodel.hxx"
37 #include "oox/helper/containerhelper.hxx"
38 #include <com/sun/star/chart2/RelativePosition.hpp>
39 #include <com/sun/star/drawing/Alignment.hpp>
40
41 #include "oox/drawingml/chart/modelbase.hxx"
42 namespace oox {
43 namespace drawingml {
44 namespace chart {
45
46 // ============================================================================
47
48 using namespace ::com::sun::star::awt;
49 using namespace ::com::sun::star::chart2;
50 using namespace ::com::sun::star::chart2::data;
51 using namespace ::com::sun::star::uno;
52
53 using ::oox::core::XmlFilterBase;
54 using ::rtl::OUString;
55 using namespace ::com::sun::star::drawing;
56
57 // ============================================================================
58
TextConverter(const ConverterRoot & rParent,TextModel & rModel)59 TextConverter::TextConverter( const ConverterRoot& rParent, TextModel& rModel ) :
60 ConverterBase< TextModel >( rParent, rModel )
61 {
62 }
63
~TextConverter()64 TextConverter::~TextConverter()
65 {
66 }
67
createDataSequence(const OUString & rRole)68 Reference< XDataSequence > TextConverter::createDataSequence( const OUString& rRole )
69 {
70 Reference< XDataSequence > xDataSeq;
71 if( mrModel.mxDataSeq.is() )
72 {
73 DataSequenceConverter aDataSeqConv( *this, *mrModel.mxDataSeq );
74 xDataSeq = aDataSeqConv.createDataSequence( rRole );
75 }
76 return xDataSeq;
77 }
78
createStringSequence(const OUString & rDefaultText,const ModelRef<TextBody> & rxTextProp,ObjectType eObjType)79 Sequence< Reference< XFormattedString > > TextConverter::createStringSequence(
80 const OUString& rDefaultText, const ModelRef< TextBody >& rxTextProp, ObjectType eObjType )
81 {
82 OSL_ENSURE( !mrModel.mxDataSeq || !mrModel.mxTextBody, "TextConverter::createStringSequence - linked string and rich text found" );
83 ::std::vector< Reference< XFormattedString > > aStringVec;
84 if( mrModel.mxTextBody.is() )
85 {
86 // rich-formatted text objects can be created, but currently Chart2 is not able to show them
87 const TextParagraphVector& rTextParas = mrModel.mxTextBody->getParagraphs();
88 for( TextParagraphVector::const_iterator aPIt = rTextParas.begin(), aPEnd = rTextParas.end(); aPIt != aPEnd; ++aPIt )
89 {
90 const TextParagraph& rTextPara = **aPIt;
91 const TextCharacterProperties& rParaProps = rTextPara.getProperties().getTextCharacterProperties();
92 for( TextRunVector::const_iterator aRIt = rTextPara.getRuns().begin(), aREnd = rTextPara.getRuns().end(); aRIt != aREnd; ++aRIt )
93 {
94 const TextRun& rTextRun = **aRIt;
95 bool bAddNewLine = (aRIt + 1 == aREnd) && (aPIt + 1 != aPEnd);
96 Reference< XFormattedString > xFmtStr = appendFormattedString( aStringVec, rTextRun.getText(), bAddNewLine );
97 PropertySet aPropSet( xFmtStr );
98 TextCharacterProperties aRunProps( rParaProps );
99 aRunProps.assignUsed( rTextRun.getTextCharacterProperties() );
100 getFormatter().convertTextFormatting( aPropSet, aRunProps, eObjType );
101 }
102 }
103 }
104 else
105 {
106 OUString aString;
107 // try to create string from linked data
108 if( mrModel.mxDataSeq.is() && !mrModel.mxDataSeq->maData.empty() )
109 mrModel.mxDataSeq->maData.begin()->second >>= aString;
110 // no linked string -> fall back to default string
111 if( aString.getLength() == 0 )
112 aString = rDefaultText;
113
114 // create formatted string object
115 if( aString.getLength() > 0 )
116 {
117 Reference< XFormattedString > xFmtStr = appendFormattedString( aStringVec, aString, false );
118 PropertySet aPropSet( xFmtStr );
119 getFormatter().convertTextFormatting( aPropSet, rxTextProp, eObjType );
120 }
121 }
122
123 return ContainerHelper::vectorToSequence( aStringVec );
124 }
125
appendFormattedString(::std::vector<Reference<XFormattedString>> & orStringVec,const OUString & rString,bool bAddNewLine) const126 Reference< XFormattedString > TextConverter::appendFormattedString(
127 ::std::vector< Reference< XFormattedString > >& orStringVec, const OUString& rString, bool bAddNewLine ) const
128 {
129 Reference< XFormattedString > xFmtStr;
130 try
131 {
132 xFmtStr.set( ConverterRoot::createInstance( CREATE_OUSTRING( "com.sun.star.chart2.FormattedString" ) ), UNO_QUERY_THROW );
133 xFmtStr->setString( bAddNewLine ? (rString + OUString( sal_Unicode( '\n' ) )) : rString );
134 orStringVec.push_back( xFmtStr );
135 }
136 catch( Exception& )
137 {
138 }
139 return xFmtStr;
140 }
141
142 // ============================================================================
143
TitleConverter(const ConverterRoot & rParent,TitleModel & rModel)144 TitleConverter::TitleConverter( const ConverterRoot& rParent, TitleModel& rModel ) :
145 ConverterBase< TitleModel >( rParent, rModel )
146 {
147 }
148
~TitleConverter()149 TitleConverter::~TitleConverter()
150 {
151 }
152
convertFromModel(const Reference<XTitled> & rxTitled,const OUString & rAutoTitle,ObjectType eObjType,sal_Int32 nMainIdx,sal_Int32 nSubIdx)153 void TitleConverter::convertFromModel( const Reference< XTitled >& rxTitled, const OUString& rAutoTitle, ObjectType eObjType, sal_Int32 nMainIdx, sal_Int32 nSubIdx )
154 {
155 if( rxTitled.is() )
156 {
157 // create the formatted strings
158 TextModel& rText = mrModel.mxText.getOrCreate();
159 TextConverter aTextConv( *this, rText );
160 Sequence< Reference< XFormattedString > > aStringSeq = aTextConv.createStringSequence( rAutoTitle, mrModel.mxTextProp, eObjType );
161 if( aStringSeq.hasElements() ) try
162 {
163 // create the title object and set the string data
164 Reference< XTitle > xTitle( createInstance( CREATE_OUSTRING( "com.sun.star.chart2.Title" ) ), UNO_QUERY_THROW );
165 xTitle->setText( aStringSeq );
166 rxTitled->setTitleObject( xTitle );
167
168 // frame formatting (text formatting already done in TextConverter::createStringSequence())
169 PropertySet aPropSet( xTitle );
170 getFormatter().convertFrameFormatting( aPropSet, mrModel.mxShapeProp, eObjType );
171
172 // frame rotation
173 OSL_ENSURE( !mrModel.mxTextProp || !rText.mxTextBody, "TitleConverter::convertFromModel - multiple text properties" );
174 ModelRef< TextBody > xTextProp = mrModel.mxTextProp.is() ? mrModel.mxTextProp : rText.mxTextBody;
175 getFormatter().convertTextRotation( aPropSet, xTextProp, true );
176
177 // register the title and layout data for conversion of position
178 registerTitleLayout( xTitle, mrModel.mxLayout, eObjType, nMainIdx, nSubIdx );
179 }
180 catch( Exception& )
181 {
182 }
183 }
184 }
185
186 // ============================================================================
187
LegendConverter(const ConverterRoot & rParent,LegendModel & rModel)188 LegendConverter::LegendConverter( const ConverterRoot& rParent, LegendModel& rModel ) :
189 ConverterBase< LegendModel >( rParent, rModel )
190 {
191 }
192
~LegendConverter()193 LegendConverter::~LegendConverter()
194 {
195 }
196
convertFromModel(const Reference<XDiagram> & rxDiagram)197 void LegendConverter::convertFromModel( const Reference< XDiagram >& rxDiagram )
198 {
199 if( rxDiagram.is() ) try
200 {
201 namespace cssc = ::com::sun::star::chart;
202 namespace cssc2 = ::com::sun::star::chart2;
203
204 // create the legend
205 Reference< XLegend > xLegend( createInstance( CREATE_OUSTRING( "com.sun.star.chart2.Legend" ) ), UNO_QUERY_THROW );
206 rxDiagram->setLegend( xLegend );
207 PropertySet aPropSet( xLegend );
208 aPropSet.setProperty( PROP_Show, true );
209
210 // legend formatting
211 getFormatter().convertFormatting( aPropSet, mrModel.mxShapeProp, mrModel.mxTextProp, OBJECTTYPE_LEGEND );
212
213 // predefined legend position and expansion
214 cssc2::LegendPosition eLegendPos = cssc2::LegendPosition_CUSTOM;
215 cssc::ChartLegendExpansion eLegendExpand = cssc::ChartLegendExpansion_CUSTOM;
216 RelativePosition eRelPos;
217 bool bTopRight=0;
218 switch( mrModel.mnPosition )
219 {
220 case XML_l:
221 eLegendPos = cssc2::LegendPosition_LINE_START;
222 eLegendExpand = cssc::ChartLegendExpansion_HIGH;
223 break;
224 case XML_r:
225 eLegendPos = cssc2::LegendPosition_LINE_END;
226 eLegendExpand = cssc::ChartLegendExpansion_HIGH;
227 break;
228 case XML_tr: // top-right not supported
229 eLegendPos = LegendPosition_CUSTOM;
230 eRelPos.Primary = 1;
231 eRelPos.Secondary =0;
232 eRelPos.Anchor = Alignment_TOP_RIGHT;
233 bTopRight=1;
234
235 break;
236 case XML_t:
237 eLegendPos = cssc2::LegendPosition_PAGE_START;
238 eLegendExpand = cssc::ChartLegendExpansion_WIDE;
239 break;
240 case XML_b:
241 eLegendPos = cssc2::LegendPosition_PAGE_END;
242 eLegendExpand = cssc::ChartLegendExpansion_WIDE;
243 break;
244 }
245 bool bManualLayout=false;
246 // manual positioning and size
247 if( mrModel.mxLayout.get() )
248 {
249 LayoutConverter aLayoutConv( *this, *mrModel.mxLayout );
250 // manual size needs ChartLegendExpansion_CUSTOM
251 if( aLayoutConv.convertFromModel( aPropSet ) )
252 eLegendExpand = cssc::ChartLegendExpansion_CUSTOM;
253 bManualLayout = !aLayoutConv.getAutoLayout();
254 }
255
256 // set position and expansion properties
257 aPropSet.setProperty( PROP_AnchorPosition, eLegendPos );
258 aPropSet.setProperty( PROP_Expansion, eLegendExpand );
259
260 if(eLegendPos == LegendPosition_CUSTOM && 1 == bTopRight && bManualLayout==false)
261 aPropSet.setProperty( PROP_RelativePosition , makeAny(eRelPos));
262 }
263 catch( Exception& )
264 {
265 }
266 }
267
268 // ============================================================================
269
270 } // namespace chart
271 } // namespace drawingml
272 } // namespace oox
273