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 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_chart2.hxx"
30 #include "TitleHelper.hxx"
31 #include "ChartModelHelper.hxx"
32 #include "macros.hxx"
33 #include "AxisHelper.hxx"
34 #include "DiagramHelper.hxx"
35 #include <com/sun/star/chart2/XChartDocument.hpp>
36 #include <rtl/ustrbuf.hxx>
37 
38 //.............................................................................
39 namespace chart
40 {
41 //.............................................................................
42 
43 using namespace ::com::sun::star;
44 using namespace ::com::sun::star::chart2;
45 using ::com::sun::star::uno::Reference;
46 
47 uno::Reference< XTitled > lcl_getTitleParentFromDiagram(
48       TitleHelper::eTitleType nTitleIndex
49     , const uno::Reference< XDiagram >& xDiagram )
50 {
51     uno::Reference< XTitled > xResult;
52 
53     if( nTitleIndex == TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION ||
54         nTitleIndex == TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION )
55     {
56         bool bDummy = false;
57         bool bIsVertical = DiagramHelper::getVertical( xDiagram, bDummy, bDummy );
58 
59         if( nTitleIndex == TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION )
60             nTitleIndex = bIsVertical ? TitleHelper::X_AXIS_TITLE : TitleHelper::Y_AXIS_TITLE;
61         else
62             nTitleIndex = bIsVertical ? TitleHelper::Y_AXIS_TITLE : TitleHelper::X_AXIS_TITLE;
63     }
64 
65 
66     switch( nTitleIndex )
67     {
68         case TitleHelper::SUB_TITLE:
69             if( xDiagram.is())
70                 xResult.set( xDiagram, uno::UNO_QUERY );
71             break;
72         case TitleHelper::X_AXIS_TITLE:
73             if( xDiagram.is())
74                 xResult.set( AxisHelper::getAxis( 0, true, xDiagram ), uno::UNO_QUERY );
75             break;
76         case TitleHelper::Y_AXIS_TITLE:
77             if( xDiagram.is())
78                 xResult.set( AxisHelper::getAxis( 1, true, xDiagram ), uno::UNO_QUERY );
79             break;
80         case TitleHelper::Z_AXIS_TITLE:
81             if( xDiagram.is())
82                 xResult.set( AxisHelper::getAxis( 2, true, xDiagram ), uno::UNO_QUERY );
83             break;
84         case TitleHelper::SECONDARY_X_AXIS_TITLE:
85             if( xDiagram.is())
86                 xResult.set( AxisHelper::getAxis( 0, false, xDiagram ), uno::UNO_QUERY );
87             break;
88         case TitleHelper::SECONDARY_Y_AXIS_TITLE:
89             if( xDiagram.is())
90                 xResult.set( AxisHelper::getAxis( 1, false, xDiagram ), uno::UNO_QUERY );
91             break;
92 
93         case TitleHelper::MAIN_TITLE:
94         default:
95             OSL_ENSURE( false, "Unsupported Title-Type requested" );
96             break;
97     }
98 
99     return xResult;
100 }
101 
102 uno::Reference< XTitled > lcl_getTitleParent( TitleHelper::eTitleType nTitleIndex
103                                               , const uno::Reference< frame::XModel >& xModel )
104 {
105     uno::Reference< XTitled > xResult;
106     uno::Reference< XChartDocument > xChartDoc( xModel, uno::UNO_QUERY );
107     uno::Reference< XDiagram > xDiagram;
108     if( xChartDoc.is())
109         xDiagram.set( xChartDoc->getFirstDiagram());
110 
111     switch( nTitleIndex )
112     {
113         case TitleHelper::MAIN_TITLE:
114             xResult.set( xModel, uno::UNO_QUERY );
115             break;
116         case TitleHelper::SUB_TITLE:
117         case TitleHelper::X_AXIS_TITLE:
118         case TitleHelper::Y_AXIS_TITLE:
119         case TitleHelper::Z_AXIS_TITLE:
120         case TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION:
121         case TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION:
122         case TitleHelper::SECONDARY_X_AXIS_TITLE:
123         case TitleHelper::SECONDARY_Y_AXIS_TITLE:
124             xResult.set( lcl_getTitleParentFromDiagram( nTitleIndex, xDiagram ));
125             break;
126         default:
127             OSL_ENSURE( false, "Unsupported Title-Type requested" );
128             break;
129     }
130 
131     return xResult;
132 }
133 
134 uno::Reference< XTitle > TitleHelper::getTitle( TitleHelper::eTitleType nTitleIndex
135                             , const uno::Reference< frame::XModel >& xModel )
136 {
137     uno::Reference< XTitled > xTitled( lcl_getTitleParent( nTitleIndex, xModel ) );
138     if( xTitled.is())
139         return xTitled->getTitleObject();
140     return NULL;
141 }
142 
143 uno::Reference< XTitle > TitleHelper::createTitle(
144       TitleHelper::eTitleType eTitleType
145     , const rtl::OUString& rTitleText
146     , const uno::Reference< frame::XModel >& xModel
147     , const uno::Reference< uno::XComponentContext > & xContext
148     , ReferenceSizeProvider * pRefSizeProvider )
149 {
150     uno::Reference< XTitle > xTitle;
151     uno::Reference< XTitled > xTitled( lcl_getTitleParent( eTitleType, xModel ) );
152 
153     if( !xTitled.is() )
154     {
155         uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xModel ) );
156         uno::Reference< chart2::XAxis > xAxis;
157         switch( eTitleType )
158         {
159             case TitleHelper::SECONDARY_X_AXIS_TITLE:
160                 xAxis = AxisHelper::createAxis( 0, false, xDiagram, xContext );
161                 break;
162             case TitleHelper::SECONDARY_Y_AXIS_TITLE:
163                 xAxis = AxisHelper::createAxis( 1, false, xDiagram, xContext );
164                break;
165             default:
166                break;
167         }
168         uno::Reference< beans::XPropertySet > xProps( xAxis, uno::UNO_QUERY );
169         if( xProps.is() )
170         {
171             xProps->setPropertyValue( C2U( "Show" ), uno::makeAny( sal_False ) );
172             xTitled = lcl_getTitleParent( eTitleType, xModel );
173         }
174     }
175 
176     if(xTitled.is())
177     {
178         uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xModel ) );
179 
180         xTitle.set( xContext->getServiceManager()->createInstanceWithContext(
181                         C2U( "com.sun.star.chart2.Title" ),
182                         xContext ), uno::UNO_QUERY );
183 
184         if(xTitle.is())
185         {
186             // default char height (main: 13.0 == default)
187             float fDefaultCharHeightSub = 11.0;
188             float fDefaultCharHeightAxis = 9.0;
189             switch( eTitleType )
190             {
191                 case TitleHelper::SUB_TITLE:
192                     TitleHelper::setCompleteString(
193                         rTitleText, xTitle, xContext, & fDefaultCharHeightSub );
194                     break;
195                 case TitleHelper::X_AXIS_TITLE:
196                 case TitleHelper::Y_AXIS_TITLE:
197                 case TitleHelper::Z_AXIS_TITLE:
198                 case TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION:
199                 case TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION:
200                 case TitleHelper::SECONDARY_X_AXIS_TITLE:
201                 case TitleHelper::SECONDARY_Y_AXIS_TITLE:
202                     TitleHelper::setCompleteString(
203                         rTitleText, xTitle, xContext, & fDefaultCharHeightAxis );
204                     break;
205                 default:
206                     TitleHelper::setCompleteString( rTitleText, xTitle, xContext );
207                     break;
208             }
209 
210             // set/clear autoscale
211             if( pRefSizeProvider )
212                 pRefSizeProvider->setValuesAtTitle( xTitle );
213 
214             xTitled->setTitleObject( xTitle );
215 
216             //default rotation 90 degree for y axis title in normal coordinatesystems or for x axis title for swapped coordinatesystems
217             if( eTitleType == TitleHelper::X_AXIS_TITLE ||
218                 eTitleType == TitleHelper::Y_AXIS_TITLE ||
219                 eTitleType == TitleHelper::SECONDARY_X_AXIS_TITLE ||
220                 eTitleType == TitleHelper::SECONDARY_Y_AXIS_TITLE )
221 
222             {
223                 try
224                 {
225                     bool bDummy = false;
226                     bool bIsVertical = DiagramHelper::getVertical( xDiagram, bDummy, bDummy );
227 
228                     Reference< beans::XPropertySet > xTitleProps( xTitle, uno::UNO_QUERY );
229                     if( xTitleProps.is() )
230                     {
231                         double fNewAngleDegree = 90.0;
232                         if( (!bIsVertical && eTitleType == TitleHelper::Y_AXIS_TITLE)
233                             || (bIsVertical && eTitleType == TitleHelper::X_AXIS_TITLE)
234                             || (!bIsVertical && eTitleType == TitleHelper::SECONDARY_Y_AXIS_TITLE)
235                             || (bIsVertical && eTitleType == TitleHelper::SECONDARY_X_AXIS_TITLE) )
236                             xTitleProps->setPropertyValue( C2U( "TextRotation" ), uno::makeAny( fNewAngleDegree ));
237                     }
238                 }
239                 catch( uno::Exception & ex )
240                 {
241                     ASSERT_EXCEPTION( ex );
242                 }
243             }
244         }
245     }
246     return xTitle;
247 
248 }
249 
250 rtl::OUString TitleHelper::getCompleteString( const uno::Reference< XTitle >& xTitle )
251 {
252     rtl::OUString aRet;
253     if(!xTitle.is())
254         return aRet;
255     uno::Sequence< uno::Reference< XFormattedString > > aStringList = xTitle->getText();
256     for( sal_Int32 nN=0; nN<aStringList.getLength();nN++ )
257         aRet += aStringList[nN]->getString();
258     return aRet;
259 }
260 
261 void TitleHelper::setCompleteString( const rtl::OUString& rNewText
262                     , const uno::Reference< XTitle >& xTitle
263                     , const uno::Reference< uno::XComponentContext > & xContext
264                     , float * pDefaultCharHeight /* = 0 */ )
265 {
266     //the format of the first old text portion will be maintained if there is any
267     if(!xTitle.is())
268         return;
269 
270     rtl::OUString aNewText = rNewText;
271 
272     bool bStacked = false;
273     uno::Reference< beans::XPropertySet > xTitleProperties( xTitle, uno::UNO_QUERY );
274     if( xTitleProperties.is() )
275         xTitleProperties->getPropertyValue( C2U( "StackCharacters" ) ) >>= bStacked;
276 
277     if( bStacked )
278     {
279         //#i99841# remove linebreaks that were added for vertical stacking
280         rtl::OUStringBuffer aUnstackedStr;
281         rtl::OUStringBuffer aSource(rNewText);
282 
283         bool bBreakIgnored = false;
284         sal_Int32 nLen = rNewText.getLength();
285         for( sal_Int32 nPos = 0; nPos < nLen; ++nPos )
286         {
287             sal_Unicode aChar = aSource.charAt( nPos );
288             if( aChar != '\n' )
289             {
290                 aUnstackedStr.append( aChar );
291                 bBreakIgnored = false;
292             }
293             else if( aChar == '\n' && bBreakIgnored )
294                 aUnstackedStr.append( aChar );
295             else
296                 bBreakIgnored = true;
297         }
298         aNewText = aUnstackedStr.makeStringAndClear();
299     }
300 
301     uno::Sequence< uno::Reference< XFormattedString > > aNewStringList(1);
302 
303     uno::Sequence< uno::Reference< XFormattedString > >  aOldStringList = xTitle->getText();
304     if( aOldStringList.getLength() )
305     {
306         aNewStringList[0].set( aOldStringList[0] );
307         aNewStringList[0]->setString( aNewText );
308     }
309     else
310     {
311         uno::Reference< uno::XInterface > xI(
312             xContext->getServiceManager()->createInstanceWithContext(
313             C2U( "com.sun.star.chart2.FormattedString" ), xContext ) );
314         uno::Reference< XFormattedString > xFormattedString( xI, uno::UNO_QUERY );
315 
316         if(xFormattedString.is())
317         {
318             xFormattedString->setString( aNewText );
319             aNewStringList[0].set( xFormattedString );
320             if( pDefaultCharHeight != 0 )
321             {
322                 try
323                 {
324                     uno::Reference< beans::XPropertySet > xProp( xFormattedString, uno::UNO_QUERY_THROW );
325 
326                     uno::Any aFontSize( uno::makeAny( *pDefaultCharHeight ));
327                     xProp->setPropertyValue( C2U("CharHeight"), aFontSize );
328                     xProp->setPropertyValue( C2U("CharHeightAsian"), aFontSize );
329                     xProp->setPropertyValue( C2U("CharHeightComplex"), aFontSize );
330                 }
331                 catch( uno::Exception & ex )
332                 {
333                     ASSERT_EXCEPTION( ex );
334                 }
335             }
336         }
337     }
338     xTitle->setText( aNewStringList );
339 }
340 
341 void TitleHelper::removeTitle( TitleHelper::eTitleType nTitleIndex
342                     , const ::com::sun::star::uno::Reference<
343                             ::com::sun::star::frame::XModel >& xModel )
344 {
345     uno::Reference< XTitled > xTitled( lcl_getTitleParent( nTitleIndex, xModel ) );
346     if( xTitled.is())
347     {
348         xTitled->setTitleObject(NULL);
349     }
350 }
351 
352 bool TitleHelper::getTitleType( eTitleType& rType
353                     , const ::com::sun::star::uno::Reference<
354                         ::com::sun::star::chart2::XTitle >& xTitle
355                     , const ::com::sun::star::uno::Reference<
356                         ::com::sun::star::frame::XModel >& xModel )
357 {
358     if( !xTitle.is() || !xModel.is() )
359         return false;
360 
361     Reference< chart2::XTitle > xCurrentTitle;
362     for( sal_Int32 nTitleType = TITLE_BEGIN; nTitleType < NORMAL_TITLE_END; nTitleType++ )
363     {
364         xCurrentTitle = TitleHelper::getTitle( static_cast<eTitleType>(nTitleType), xModel );
365         if( xCurrentTitle == xTitle )
366         {
367             rType = static_cast<eTitleType>(nTitleType);
368             return true;
369         }
370     }
371 
372     return false;
373 }
374 
375 //.............................................................................
376 } //namespace chart
377 //.............................................................................
378 
379