1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include "oox/drawingml/chart/titleconverter.hxx"
29 
30 #include <com/sun/star/chart/ChartLegendExpansion.hpp>
31 #include <com/sun/star/chart2/LegendPosition.hpp>
32 #include <com/sun/star/chart2/XDiagram.hpp>
33 #include <com/sun/star/chart2/XFormattedString.hpp>
34 #include <com/sun/star/chart2/XLegend.hpp>
35 #include <com/sun/star/chart2/XTitle.hpp>
36 #include <com/sun/star/chart2/XTitled.hpp>
37 #include "oox/drawingml/textbody.hxx"
38 #include "oox/drawingml/textparagraph.hxx"
39 #include "oox/drawingml/chart/datasourceconverter.hxx"
40 #include "oox/drawingml/chart/titlemodel.hxx"
41 #include "oox/helper/containerhelper.hxx"
42 
43 namespace oox {
44 namespace drawingml {
45 namespace chart {
46 
47 // ============================================================================
48 
49 using namespace ::com::sun::star::awt;
50 using namespace ::com::sun::star::chart2;
51 using namespace ::com::sun::star::chart2::data;
52 using namespace ::com::sun::star::uno;
53 
54 using ::oox::core::XmlFilterBase;
55 using ::rtl::OUString;
56 
57 // ============================================================================
58 
59 TextConverter::TextConverter( const ConverterRoot& rParent, TextModel& rModel ) :
60     ConverterBase< TextModel >( rParent, rModel )
61 {
62 }
63 
64 TextConverter::~TextConverter()
65 {
66 }
67 
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 
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 
126 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 
144 TitleConverter::TitleConverter( const ConverterRoot& rParent, TitleModel& rModel ) :
145     ConverterBase< TitleModel >( rParent, rModel )
146 {
147 }
148 
149 TitleConverter::~TitleConverter()
150 {
151 }
152 
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 
188 LegendConverter::LegendConverter( const ConverterRoot& rParent, LegendModel& rModel ) :
189     ConverterBase< LegendModel >( rParent, rModel )
190 {
191 }
192 
193 LegendConverter::~LegendConverter()
194 {
195 }
196 
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         switch( mrModel.mnPosition )
217         {
218             case XML_l:
219                 eLegendPos = cssc2::LegendPosition_LINE_START;
220                 eLegendExpand = cssc::ChartLegendExpansion_HIGH;
221             break;
222             case XML_r:
223             case XML_tr:    // top-right not supported
224                 eLegendPos = cssc2::LegendPosition_LINE_END;
225                 eLegendExpand = cssc::ChartLegendExpansion_HIGH;
226             break;
227             case XML_t:
228                 eLegendPos = cssc2::LegendPosition_PAGE_START;
229                 eLegendExpand = cssc::ChartLegendExpansion_WIDE;
230             break;
231             case XML_b:
232                 eLegendPos = cssc2::LegendPosition_PAGE_END;
233                 eLegendExpand = cssc::ChartLegendExpansion_WIDE;
234             break;
235         }
236 
237         // manual positioning and size
238         if( mrModel.mxLayout.get() )
239         {
240             LayoutConverter aLayoutConv( *this, *mrModel.mxLayout );
241             // manual size needs ChartLegendExpansion_CUSTOM
242             if( aLayoutConv.convertFromModel( aPropSet ) )
243                 eLegendExpand = cssc::ChartLegendExpansion_CUSTOM;
244         }
245 
246         // set position and expansion properties
247         aPropSet.setProperty( PROP_AnchorPosition, eLegendPos );
248         aPropSet.setProperty( PROP_Expansion, eLegendExpand );
249     }
250     catch( Exception& )
251     {
252     }
253 }
254 
255 // ============================================================================
256 
257 } // namespace chart
258 } // namespace drawingml
259 } // namespace oox
260