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 
39 namespace oox {
40 namespace drawingml {
41 namespace chart {
42 
43 // ============================================================================
44 
45 using namespace ::com::sun::star::awt;
46 using namespace ::com::sun::star::chart2;
47 using namespace ::com::sun::star::chart2::data;
48 using namespace ::com::sun::star::uno;
49 
50 using ::oox::core::XmlFilterBase;
51 using ::rtl::OUString;
52 
53 // ============================================================================
54 
55 TextConverter::TextConverter( const ConverterRoot& rParent, TextModel& rModel ) :
56     ConverterBase< TextModel >( rParent, rModel )
57 {
58 }
59 
60 TextConverter::~TextConverter()
61 {
62 }
63 
64 Reference< XDataSequence > TextConverter::createDataSequence( const OUString& rRole )
65 {
66     Reference< XDataSequence > xDataSeq;
67     if( mrModel.mxDataSeq.is() )
68     {
69         DataSequenceConverter aDataSeqConv( *this, *mrModel.mxDataSeq );
70         xDataSeq = aDataSeqConv.createDataSequence( rRole );
71     }
72     return xDataSeq;
73 }
74 
75 Sequence< Reference< XFormattedString > > TextConverter::createStringSequence(
76         const OUString& rDefaultText, const ModelRef< TextBody >& rxTextProp, ObjectType eObjType )
77 {
78     OSL_ENSURE( !mrModel.mxDataSeq || !mrModel.mxTextBody, "TextConverter::createStringSequence - linked string and rich text found" );
79     ::std::vector< Reference< XFormattedString > > aStringVec;
80     if( mrModel.mxTextBody.is() )
81     {
82         // rich-formatted text objects can be created, but currently Chart2 is not able to show them
83         const TextParagraphVector& rTextParas = mrModel.mxTextBody->getParagraphs();
84         for( TextParagraphVector::const_iterator aPIt = rTextParas.begin(), aPEnd = rTextParas.end(); aPIt != aPEnd; ++aPIt )
85         {
86             const TextParagraph& rTextPara = **aPIt;
87             const TextCharacterProperties& rParaProps = rTextPara.getProperties().getTextCharacterProperties();
88             for( TextRunVector::const_iterator aRIt = rTextPara.getRuns().begin(), aREnd = rTextPara.getRuns().end(); aRIt != aREnd; ++aRIt )
89             {
90                 const TextRun& rTextRun = **aRIt;
91                 bool bAddNewLine = (aRIt + 1 == aREnd) && (aPIt + 1 != aPEnd);
92                 Reference< XFormattedString > xFmtStr = appendFormattedString( aStringVec, rTextRun.getText(), bAddNewLine );
93                 PropertySet aPropSet( xFmtStr );
94                 TextCharacterProperties aRunProps( rParaProps );
95                 aRunProps.assignUsed( rTextRun.getTextCharacterProperties() );
96                 getFormatter().convertTextFormatting( aPropSet, aRunProps, eObjType );
97             }
98         }
99     }
100     else
101     {
102         OUString aString;
103         // try to create string from linked data
104         if( mrModel.mxDataSeq.is() && !mrModel.mxDataSeq->maData.empty() )
105             mrModel.mxDataSeq->maData.begin()->second >>= aString;
106         // no linked string -> fall back to default string
107         if( aString.getLength() == 0 )
108             aString = rDefaultText;
109 
110         // create formatted string object
111         if( aString.getLength() > 0 )
112         {
113             Reference< XFormattedString > xFmtStr = appendFormattedString( aStringVec, aString, false );
114             PropertySet aPropSet( xFmtStr );
115             getFormatter().convertTextFormatting( aPropSet, rxTextProp, eObjType );
116         }
117     }
118 
119     return ContainerHelper::vectorToSequence( aStringVec );
120 }
121 
122 Reference< XFormattedString > TextConverter::appendFormattedString(
123         ::std::vector< Reference< XFormattedString > >& orStringVec, const OUString& rString, bool bAddNewLine ) const
124 {
125     Reference< XFormattedString > xFmtStr;
126     try
127     {
128         xFmtStr.set( ConverterRoot::createInstance( CREATE_OUSTRING( "com.sun.star.chart2.FormattedString" ) ), UNO_QUERY_THROW );
129         xFmtStr->setString( bAddNewLine ? (rString + OUString( sal_Unicode( '\n' ) )) : rString );
130         orStringVec.push_back( xFmtStr );
131     }
132     catch( Exception& )
133     {
134     }
135     return xFmtStr;
136 }
137 
138 // ============================================================================
139 
140 TitleConverter::TitleConverter( const ConverterRoot& rParent, TitleModel& rModel ) :
141     ConverterBase< TitleModel >( rParent, rModel )
142 {
143 }
144 
145 TitleConverter::~TitleConverter()
146 {
147 }
148 
149 void TitleConverter::convertFromModel( const Reference< XTitled >& rxTitled, const OUString& rAutoTitle, ObjectType eObjType, sal_Int32 nMainIdx, sal_Int32 nSubIdx )
150 {
151     if( rxTitled.is() )
152     {
153         // create the formatted strings
154         TextModel& rText = mrModel.mxText.getOrCreate();
155         TextConverter aTextConv( *this, rText );
156         Sequence< Reference< XFormattedString > > aStringSeq = aTextConv.createStringSequence( rAutoTitle, mrModel.mxTextProp, eObjType );
157         if( aStringSeq.hasElements() ) try
158         {
159             // create the title object and set the string data
160             Reference< XTitle > xTitle( createInstance( CREATE_OUSTRING( "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" );
170             ModelRef< TextBody > xTextProp = mrModel.mxTextProp.is() ? mrModel.mxTextProp : rText.mxTextBody;
171             getFormatter().convertTextRotation( aPropSet, xTextProp, true );
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 }
181 
182 // ============================================================================
183 
184 LegendConverter::LegendConverter( const ConverterRoot& rParent, LegendModel& rModel ) :
185     ConverterBase< LegendModel >( rParent, rModel )
186 {
187 }
188 
189 LegendConverter::~LegendConverter()
190 {
191 }
192 
193 void LegendConverter::convertFromModel( const Reference< XDiagram >& rxDiagram )
194 {
195     if( rxDiagram.is() ) 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( CREATE_OUSTRING( "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
207         getFormatter().convertFormatting( aPropSet, mrModel.mxShapeProp, mrModel.mxTextProp, OBJECTTYPE_LEGEND );
208 
209         // predefined legend position and expansion
210         cssc2::LegendPosition eLegendPos = cssc2::LegendPosition_CUSTOM;
211         cssc::ChartLegendExpansion eLegendExpand = cssc::ChartLegendExpansion_CUSTOM;
212         switch( mrModel.mnPosition )
213         {
214             case XML_l:
215                 eLegendPos = cssc2::LegendPosition_LINE_START;
216                 eLegendExpand = cssc::ChartLegendExpansion_HIGH;
217             break;
218             case XML_r:
219             case XML_tr:    // top-right not supported
220                 eLegendPos = cssc2::LegendPosition_LINE_END;
221                 eLegendExpand = cssc::ChartLegendExpansion_HIGH;
222             break;
223             case XML_t:
224                 eLegendPos = cssc2::LegendPosition_PAGE_START;
225                 eLegendExpand = cssc::ChartLegendExpansion_WIDE;
226             break;
227             case XML_b:
228                 eLegendPos = cssc2::LegendPosition_PAGE_END;
229                 eLegendExpand = cssc::ChartLegendExpansion_WIDE;
230             break;
231         }
232 
233         // manual positioning and size
234         if( mrModel.mxLayout.get() )
235         {
236             LayoutConverter aLayoutConv( *this, *mrModel.mxLayout );
237             // manual size needs ChartLegendExpansion_CUSTOM
238             if( aLayoutConv.convertFromModel( aPropSet ) )
239                 eLegendExpand = cssc::ChartLegendExpansion_CUSTOM;
240         }
241 
242         // set position and expansion properties
243         aPropSet.setProperty( PROP_AnchorPosition, eLegendPos );
244         aPropSet.setProperty( PROP_Expansion, eLegendExpand );
245     }
246     catch( Exception& )
247     {
248     }
249 }
250 
251 // ============================================================================
252 
253 } // namespace chart
254 } // namespace drawingml
255 } // namespace oox
256