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 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_chart2.hxx"
26 #include "VAxisProperties.hxx"
27 #include "macros.hxx"
28 #include "ViewDefines.hxx"
29 #include "CommonConverters.hxx"
30 #include "AxisHelper.hxx"
31 #include "DiagramHelper.hxx"
32 #include "ChartModelHelper.hxx"
33
34 #include <tools/color.hxx>
35 #include <com/sun/star/beans/XPropertySet.hpp>
36 #include <com/sun/star/chart/ChartAxisArrangeOrderType.hpp>
37 #include <com/sun/star/drawing/LineStyle.hpp>
38 #include <com/sun/star/text/WritingMode2.hpp>
39
40 //.............................................................................
41 namespace chart
42 {
43 //.............................................................................
44 using namespace ::com::sun::star;
45 using namespace ::com::sun::star::chart2;
46
lcl_calcTickLengthForDepth(sal_Int32 nDepth,sal_Int32 nTickmarkStyle)47 sal_Int32 lcl_calcTickLengthForDepth(sal_Int32 nDepth,sal_Int32 nTickmarkStyle)
48 {
49 sal_Int32 nWidth = AXIS2D_TICKLENGTH; //@maybefuturetodo this length could be offered by the model
50 double fPercent = 1.0;
51 switch(nDepth)
52 {
53 case 0:
54 fPercent = 1.0;
55 break;
56 case 1:
57 fPercent = 0.75;//percentage like in the old chart
58 break;
59 case 2:
60 fPercent = 0.5;
61 break;
62 default:
63 fPercent = 0.3;
64 break;
65 }
66 if(nTickmarkStyle==3)//inner and outer tickmarks
67 fPercent*=2.0;
68 return static_cast<sal_Int32>(nWidth*fPercent);
69 }
70
lcl_getTickOffset(sal_Int32 nLength,sal_Int32 nTickmarkStyle)71 double lcl_getTickOffset(sal_Int32 nLength,sal_Int32 nTickmarkStyle)
72 {
73 double fPercent = 0.0; //0<=fPercent<=1
74 //0.0: completely inner
75 //1.0: completely outer
76 //0.5: half and half
77
78 /*
79 nTickmarkStyle:
80 1: inner tickmarks
81 2: outer tickmarks
82 3: inner and outer tickmarks
83 */
84 switch(nTickmarkStyle)
85 {
86 case 1:
87 fPercent = 0.0;
88 break;
89 case 2:
90 fPercent = 1.0;
91 break;
92 default:
93 fPercent = 0.5;
94 break;
95 }
96 return fPercent*nLength;
97 }
98
makeLinePropertiesForDepth(sal_Int32) const99 VLineProperties AxisProperties::makeLinePropertiesForDepth( sal_Int32 /* nDepth */ ) const
100 {
101 //@todo get this from somewhere; maybe for each subincrement
102 //so far the model does not offer different settings for each tick depth
103 return m_aLineProperties;
104 }
105
makeTickmarkProperties(sal_Int32 nDepth) const106 TickmarkProperties AxisProperties::makeTickmarkProperties(
107 sal_Int32 nDepth ) const
108 {
109 /*
110 nTickmarkStyle:
111 1: inner tickmarks
112 2: outer tickmarks
113 3: inner and outer tickmarks
114 */
115 sal_Int32 nTickmarkStyle = 1;
116 if(nDepth==0)
117 {
118 nTickmarkStyle = m_nMajorTickmarks;
119 if(!nTickmarkStyle)
120 {
121 //create major tickmarks as if they were minor tickmarks
122 nDepth = 1;
123 nTickmarkStyle = m_nMinorTickmarks;
124 }
125 }
126 else if( nDepth==1)
127 {
128 nTickmarkStyle = m_nMinorTickmarks;
129 }
130
131 if( m_fInnerDirectionSign == 0.0 )
132 {
133 if( nTickmarkStyle != 0 )
134 nTickmarkStyle = 3; //inner and outer tickmarks
135 }
136
137 TickmarkProperties aTickmarkProperties;
138 aTickmarkProperties.Length = lcl_calcTickLengthForDepth(nDepth,nTickmarkStyle);
139 aTickmarkProperties.RelativePos = static_cast<sal_Int32>(lcl_getTickOffset(aTickmarkProperties.Length,nTickmarkStyle));
140 aTickmarkProperties.aLineProperties = this->makeLinePropertiesForDepth( nDepth );
141 return aTickmarkProperties;
142 }
143
makeTickmarkPropertiesForComplexCategories(sal_Int32 nTickLength,sal_Int32 nTickStartDistanceToAxis,sal_Int32) const144 TickmarkProperties AxisProperties::makeTickmarkPropertiesForComplexCategories(
145 sal_Int32 nTickLength, sal_Int32 nTickStartDistanceToAxis, sal_Int32 /*nTextLevel*/ ) const
146 {
147 sal_Int32 nTickmarkStyle = (m_fLabelDirectionSign==m_fInnerDirectionSign) ? 2/*outside*/ : 1/*inside*/;
148
149 TickmarkProperties aTickmarkProperties;
150 aTickmarkProperties.Length = nTickLength;// + nTextLevel*( lcl_calcTickLengthForDepth(0,nTickmarkStyle) );
151 aTickmarkProperties.RelativePos = static_cast<sal_Int32>(lcl_getTickOffset(aTickmarkProperties.Length+nTickStartDistanceToAxis,nTickmarkStyle));
152 aTickmarkProperties.aLineProperties = this->makeLinePropertiesForDepth( 0 );
153 return aTickmarkProperties;
154 }
155
getBiggestTickmarkProperties()156 TickmarkProperties AxisProperties::getBiggestTickmarkProperties()
157 {
158 TickmarkProperties aTickmarkProperties;
159 sal_Int32 nDepth = 0;
160 sal_Int32 nTickmarkStyle = 3;//inner and outer tickmarks
161 aTickmarkProperties.Length = lcl_calcTickLengthForDepth( nDepth,nTickmarkStyle );
162 aTickmarkProperties.RelativePos = static_cast<sal_Int32>( lcl_getTickOffset( aTickmarkProperties.Length, nTickmarkStyle ) );
163 return aTickmarkProperties;
164 }
165
166 //--------------------------------------------------------------------------
167
AxisProperties(const uno::Reference<XAxis> & xAxisModel,ExplicitCategoriesProvider * pExplicitCategoriesProvider)168 AxisProperties::AxisProperties( const uno::Reference< XAxis >& xAxisModel
169 , ExplicitCategoriesProvider* pExplicitCategoriesProvider )
170 : m_xAxisModel(xAxisModel)
171 , m_nDimensionIndex(0)
172 , m_bIsMainAxis(true)
173 , m_bSwapXAndY(false)
174 , m_eCrossoverType( ::com::sun::star::chart::ChartAxisPosition_ZERO )
175 , m_eLabelPos( ::com::sun::star::chart::ChartAxisLabelPosition_NEAR_AXIS )
176 , m_eTickmarkPos( ::com::sun::star::chart::ChartAxisMarkPosition_AT_LABELS_AND_AXIS )
177 , m_pfMainLinePositionAtOtherAxis(NULL)
178 , m_pfExrtaLinePositionAtOtherAxis(NULL)
179 , m_bCrossingAxisHasReverseDirection(false)
180 , m_bCrossingAxisIsCategoryAxes(false)
181 , m_fLabelDirectionSign(1.0)
182 , m_fInnerDirectionSign(1.0)
183 , m_aLabelAlignment(LABEL_ALIGN_RIGHT_TOP)
184 , m_bDisplayLabels( true )
185 , m_nNumberFormatKey(0)
186 , m_nMajorTickmarks(1)
187 , m_nMinorTickmarks(1)
188 , m_aTickmarkPropertiesList()
189 , m_aLineProperties()
190 //for category axes
191 , m_nAxisType(AxisType::REALNUMBER)
192 , m_bComplexCategories(false)
193 , m_pExplicitCategoriesProvider(pExplicitCategoriesProvider)
194 , m_xAxisTextProvider(0)
195 {
196 }
197
AxisProperties(const AxisProperties & rAxisProperties)198 AxisProperties::AxisProperties( const AxisProperties& rAxisProperties )
199 : m_xAxisModel( rAxisProperties.m_xAxisModel )
200 , m_nDimensionIndex( rAxisProperties.m_nDimensionIndex )
201 , m_bIsMainAxis( rAxisProperties.m_bIsMainAxis )
202 , m_bSwapXAndY( rAxisProperties.m_bSwapXAndY )
203 , m_eCrossoverType( rAxisProperties.m_eCrossoverType )
204 , m_eLabelPos( rAxisProperties.m_eLabelPos )
205 , m_eTickmarkPos( rAxisProperties.m_eTickmarkPos )
206 , m_pfMainLinePositionAtOtherAxis( NULL )
207 , m_pfExrtaLinePositionAtOtherAxis( NULL )
208 , m_bCrossingAxisHasReverseDirection( rAxisProperties.m_bCrossingAxisHasReverseDirection )
209 , m_bCrossingAxisIsCategoryAxes( rAxisProperties.m_bCrossingAxisIsCategoryAxes )
210 , m_fLabelDirectionSign( rAxisProperties.m_fLabelDirectionSign )
211 , m_fInnerDirectionSign( rAxisProperties.m_fInnerDirectionSign )
212 , m_aLabelAlignment( rAxisProperties.m_aLabelAlignment )
213 , m_bDisplayLabels( rAxisProperties.m_bDisplayLabels )
214 , m_nNumberFormatKey( rAxisProperties.m_nNumberFormatKey )
215 , m_nMajorTickmarks( rAxisProperties.m_nMajorTickmarks )
216 , m_nMinorTickmarks( rAxisProperties.m_nMinorTickmarks )
217 , m_aTickmarkPropertiesList( rAxisProperties.m_aTickmarkPropertiesList )
218 , m_aLineProperties( rAxisProperties.m_aLineProperties )
219 //for category axes
220 , m_nAxisType( rAxisProperties.m_nAxisType )
221 , m_bComplexCategories( rAxisProperties.m_bComplexCategories )
222 , m_pExplicitCategoriesProvider( rAxisProperties.m_pExplicitCategoriesProvider )
223 , m_xAxisTextProvider( rAxisProperties.m_xAxisTextProvider )
224 {
225 if( rAxisProperties.m_pfMainLinePositionAtOtherAxis )
226 m_pfMainLinePositionAtOtherAxis = new double(*rAxisProperties.m_pfMainLinePositionAtOtherAxis);
227 if( rAxisProperties.m_pfExrtaLinePositionAtOtherAxis )
228 m_pfExrtaLinePositionAtOtherAxis = new double (*rAxisProperties.m_pfExrtaLinePositionAtOtherAxis);
229 }
230
~AxisProperties()231 AxisProperties::~AxisProperties()
232 {
233 delete m_pfMainLinePositionAtOtherAxis;
234 delete m_pfExrtaLinePositionAtOtherAxis;
235 }
236
lcl_getLabelAlignmentForZAxis(const AxisProperties & rAxisProperties)237 LabelAlignment lcl_getLabelAlignmentForZAxis( const AxisProperties& rAxisProperties )
238 {
239 LabelAlignment aRet( LABEL_ALIGN_RIGHT );
240 if( rAxisProperties.m_fLabelDirectionSign<0 )
241 aRet = LABEL_ALIGN_LEFT;
242 return aRet;
243 }
244
lcl_getLabelAlignmentForYAxis(const AxisProperties & rAxisProperties)245 LabelAlignment lcl_getLabelAlignmentForYAxis( const AxisProperties& rAxisProperties )
246 {
247 LabelAlignment aRet( LABEL_ALIGN_RIGHT );
248 if( rAxisProperties.m_fLabelDirectionSign<0 )
249 aRet = LABEL_ALIGN_LEFT;
250 return aRet;
251 }
252
lcl_getLabelAlignmentForXAxis(const AxisProperties & rAxisProperties)253 LabelAlignment lcl_getLabelAlignmentForXAxis( const AxisProperties& rAxisProperties )
254 {
255 LabelAlignment aRet( LABEL_ALIGN_BOTTOM );
256 if( rAxisProperties.m_fLabelDirectionSign<0 )
257 aRet = LABEL_ALIGN_TOP;
258 return aRet;
259 }
260
initAxisPositioning(const uno::Reference<beans::XPropertySet> & xAxisProp)261 void AxisProperties::initAxisPositioning( const uno::Reference< beans::XPropertySet >& xAxisProp )
262 {
263 if( !xAxisProp.is() )
264 return;
265 try
266 {
267 if( AxisHelper::isAxisPositioningEnabled() )
268 {
269 xAxisProp->getPropertyValue(C2U( "CrossoverPosition" )) >>= m_eCrossoverType;
270 if( ::com::sun::star::chart::ChartAxisPosition_VALUE == m_eCrossoverType )
271 {
272 double fValue = 0.0;
273 xAxisProp->getPropertyValue(C2U( "CrossoverValue" )) >>= fValue;
274
275 if( m_bCrossingAxisIsCategoryAxes )
276 fValue = ::rtl::math::round(fValue);
277 m_pfMainLinePositionAtOtherAxis = new double(fValue);
278 }
279 else if( ::com::sun::star::chart::ChartAxisPosition_ZERO == m_eCrossoverType )
280 m_pfMainLinePositionAtOtherAxis = new double(0.0);
281
282 xAxisProp->getPropertyValue(C2U( "LabelPosition" )) >>= m_eLabelPos;
283 xAxisProp->getPropertyValue(C2U( "MarkPosition" )) >>= m_eTickmarkPos;
284 }
285 else
286 {
287 m_eCrossoverType = ::com::sun::star::chart::ChartAxisPosition_START;
288 if( m_bIsMainAxis == m_bCrossingAxisHasReverseDirection )
289 m_eCrossoverType = ::com::sun::star::chart::ChartAxisPosition_END;
290 m_eLabelPos = ::com::sun::star::chart::ChartAxisLabelPosition_NEAR_AXIS;
291 m_eTickmarkPos = ::com::sun::star::chart::ChartAxisMarkPosition_AT_LABELS;
292 }
293 }
294 catch( uno::Exception& e )
295 {
296 ASSERT_EXCEPTION( e );
297 }
298 }
299
init(bool bCartesian)300 void AxisProperties::init( bool bCartesian )
301 {
302 uno::Reference< beans::XPropertySet > xProp =
303 uno::Reference<beans::XPropertySet>::query( this->m_xAxisModel );
304 if( !xProp.is() )
305 return;
306
307 if( m_nDimensionIndex<2 )
308 initAxisPositioning( xProp );
309
310 ScaleData aScaleData = m_xAxisModel->getScaleData();
311 if( m_nDimensionIndex==0 )
312 AxisHelper::checkDateAxis( aScaleData, m_pExplicitCategoriesProvider, bCartesian );
313 m_nAxisType = aScaleData.AxisType;
314
315 if( bCartesian )
316 {
317 if( m_nDimensionIndex == 0 && m_nAxisType == AxisType::CATEGORY
318 && m_pExplicitCategoriesProvider && m_pExplicitCategoriesProvider->hasComplexCategories() )
319 m_bComplexCategories = true;
320
321 if( ::com::sun::star::chart::ChartAxisPosition_END == m_eCrossoverType )
322 m_fInnerDirectionSign = m_bCrossingAxisHasReverseDirection ? 1 : -1;
323 else
324 m_fInnerDirectionSign = m_bCrossingAxisHasReverseDirection ? -1 : 1;
325
326 if( ::com::sun::star::chart::ChartAxisLabelPosition_NEAR_AXIS == m_eLabelPos )
327 m_fLabelDirectionSign = m_fInnerDirectionSign;
328 else if( ::com::sun::star::chart::ChartAxisLabelPosition_NEAR_AXIS_OTHER_SIDE == m_eLabelPos )
329 m_fLabelDirectionSign = -m_fInnerDirectionSign;
330 else if( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_START == m_eLabelPos )
331 m_fLabelDirectionSign = m_bCrossingAxisHasReverseDirection ? -1 : 1;
332 else if( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_END == m_eLabelPos )
333 m_fLabelDirectionSign = m_bCrossingAxisHasReverseDirection ? 1 : -1;
334
335 if( m_nDimensionIndex==2 )
336 m_aLabelAlignment = lcl_getLabelAlignmentForZAxis(*this);
337 else
338 {
339 bool bIsYAxisPosition = (m_nDimensionIndex==1 && !m_bSwapXAndY)
340 || (m_nDimensionIndex==0 && m_bSwapXAndY);
341 if( bIsYAxisPosition )
342 {
343 m_fLabelDirectionSign*=-1;
344 m_fInnerDirectionSign*=-1;
345 }
346
347 if( bIsYAxisPosition )
348 m_aLabelAlignment = lcl_getLabelAlignmentForYAxis(*this);
349 else
350 m_aLabelAlignment = lcl_getLabelAlignmentForXAxis(*this);
351 }
352 }
353
354 try
355 {
356 //init LineProperties
357 m_aLineProperties.initFromPropertySet( xProp );
358
359 //init display labels
360 xProp->getPropertyValue( C2U( "DisplayLabels" ) ) >>= m_bDisplayLabels;
361
362 //init TickmarkProperties
363 xProp->getPropertyValue( C2U( "MajorTickmarks" ) ) >>= m_nMajorTickmarks;
364 xProp->getPropertyValue( C2U( "MinorTickmarks" ) ) >>= m_nMinorTickmarks;
365
366 sal_Int32 nMaxDepth = 0;
367 if(m_nMinorTickmarks!=0)
368 nMaxDepth=2;
369 else if(m_nMajorTickmarks!=0)
370 nMaxDepth=1;
371
372 this->m_aTickmarkPropertiesList.clear();
373 for( sal_Int32 nDepth=0; nDepth<nMaxDepth; nDepth++ )
374 {
375 TickmarkProperties aTickmarkProperties = this->makeTickmarkProperties( nDepth );
376 this->m_aTickmarkPropertiesList.push_back( aTickmarkProperties );
377 }
378 }
379 catch( uno::Exception& e )
380 {
381 ASSERT_EXCEPTION( e );
382 }
383 }
384
385 //-----------------------------------------------------------------------------
386
AxisLabelProperties()387 AxisLabelProperties::AxisLabelProperties()
388 : m_aFontReferenceSize( ChartModelHelper::getDefaultPageSize() )
389 , m_aMaximumSpaceForLabels( 0 , 0, m_aFontReferenceSize.Width, m_aFontReferenceSize.Height )
390 , nNumberFormatKey(0)
391 , eStaggering( SIDE_BY_SIDE )
392 , bLineBreakAllowed( false )
393 , bOverlapAllowed( false )
394 , bStackCharacters( false )
395 , fRotationAngleDegree( 0.0 )
396 , nRhythm( 1 )
397 , bRhythmIsFix(false)
398 {
399 /*
400 aLocale.Language = C2U( "en" );
401 aLocale.Country = C2U( "US" );
402
403 //aLocale.Language = C2U( "ar" );
404 //aLocale.Country = C2U( "IR" );
405
406 //aLocale.Language = C2U( "ja" );
407 //aLocale.Country = C2U( "JP" );
408 */
409 }
410
init(const uno::Reference<XAxis> & xAxisModel)411 void AxisLabelProperties::init( const uno::Reference< XAxis >& xAxisModel )
412 {
413 uno::Reference< beans::XPropertySet > xProp =
414 uno::Reference<beans::XPropertySet>::query( xAxisModel );
415 if(xProp.is())
416 {
417 try
418 {
419 xProp->getPropertyValue( C2U( "TextBreak" ) ) >>= this->bLineBreakAllowed;
420 xProp->getPropertyValue( C2U( "TextOverlap" ) ) >>= this->bOverlapAllowed;
421 xProp->getPropertyValue( C2U( "StackCharacters" ) ) >>= this->bStackCharacters;
422 xProp->getPropertyValue( C2U( "TextRotation" ) ) >>= this->fRotationAngleDegree;
423
424 ::com::sun::star::chart::ChartAxisArrangeOrderType eArrangeOrder;
425 xProp->getPropertyValue( C2U( "ArrangeOrder" ) ) >>= eArrangeOrder;
426 switch(eArrangeOrder)
427 {
428 case ::com::sun::star::chart::ChartAxisArrangeOrderType_SIDE_BY_SIDE:
429 this->eStaggering = SIDE_BY_SIDE;
430 break;
431 case ::com::sun::star::chart::ChartAxisArrangeOrderType_STAGGER_EVEN:
432 this->eStaggering = STAGGER_EVEN;
433 break;
434 case ::com::sun::star::chart::ChartAxisArrangeOrderType_STAGGER_ODD:
435 this->eStaggering = STAGGER_ODD;
436 break;
437 default:
438 this->eStaggering = STAGGER_AUTO;
439 break;
440 }
441 }
442 catch( uno::Exception& e )
443 {
444 ASSERT_EXCEPTION( e );
445 }
446 }
447 }
448
449 /*
450 sal_Int16 getSwappedWritingMode( sal_Int16 nWritingMode )
451 {
452 //LR_TB == LT
453 //RL_TB == RT (Arabic, Hebrew)
454 //TB_RL == TR (Japanese, Chinese, Korean)
455 // ?? TL (Mongolian) see also text::WritingMode2
456
457 switch(nWritingMode)
458 {
459 case text::WritingMode2::RL_TB:
460 return text::WritingMode2::TB_RL;
461 case text::WritingMode2::TB_RL:
462 return text::WritingMode2::RL_TB;
463 case text::WritingMode2::LR_TB:
464 return text::WritingMode2::TB_LR;
465 default:
466 return text::WritingMode2::LR_TB;
467 }
468 }
469 */
470
getIsStaggered() const471 sal_Bool AxisLabelProperties::getIsStaggered() const
472 {
473 if( STAGGER_ODD == eStaggering || STAGGER_EVEN == eStaggering )
474 return sal_True;
475 return sal_False;
476 }
477
478 //.............................................................................
479 } //namespace chart
480 //.............................................................................
481