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