Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "VAxisProperties.hxx"
21 : #include "macros.hxx"
22 : #include "ViewDefines.hxx"
23 : #include "CommonConverters.hxx"
24 : #include "AxisHelper.hxx"
25 : #include "DiagramHelper.hxx"
26 : #include "ChartModelHelper.hxx"
27 :
28 : #include <com/sun/star/beans/XPropertySet.hpp>
29 : #include <com/sun/star/chart/ChartAxisArrangeOrderType.hpp>
30 : #include <com/sun/star/drawing/LineStyle.hpp>
31 : #include <com/sun/star/text/WritingMode2.hpp>
32 :
33 : namespace chart
34 : {
35 : using namespace ::com::sun::star;
36 : using namespace ::com::sun::star::chart2;
37 :
38 0 : sal_Int32 lcl_calcTickLengthForDepth(sal_Int32 nDepth,sal_Int32 nTickmarkStyle)
39 : {
40 0 : sal_Int32 nWidth = AXIS2D_TICKLENGTH; //@maybefuturetodo this length could be offered by the model
41 0 : double fPercent = 1.0;
42 0 : switch(nDepth)
43 : {
44 : case 0:
45 0 : fPercent = 1.0;
46 0 : break;
47 : case 1:
48 0 : fPercent = 0.75;//percentage like in the old chart
49 0 : break;
50 : case 2:
51 0 : fPercent = 0.5;
52 0 : break;
53 : default:
54 0 : fPercent = 0.3;
55 0 : break;
56 : }
57 0 : if(nTickmarkStyle==3)//inner and outer tickmarks
58 0 : fPercent*=2.0;
59 0 : return static_cast<sal_Int32>(nWidth*fPercent);
60 : }
61 :
62 0 : double lcl_getTickOffset(sal_Int32 nLength,sal_Int32 nTickmarkStyle)
63 : {
64 0 : double fPercent = 0.0; //0<=fPercent<=1
65 : //0.0: completely inner
66 : //1.0: completely outer
67 : //0.5: half and half
68 :
69 : /*
70 : nTickmarkStyle:
71 : 1: inner tickmarks
72 : 2: outer tickmarks
73 : 3: inner and outer tickmarks
74 : */
75 0 : switch(nTickmarkStyle)
76 : {
77 : case 1:
78 0 : fPercent = 0.0;
79 0 : break;
80 : case 2:
81 0 : fPercent = 1.0;
82 0 : break;
83 : default:
84 0 : fPercent = 0.5;
85 0 : break;
86 : }
87 0 : return fPercent*nLength;
88 : }
89 :
90 0 : VLineProperties AxisProperties::makeLinePropertiesForDepth( sal_Int32 /* nDepth */ ) const
91 : {
92 : //@todo get this from somewhere; maybe for each subincrement
93 : //so far the model does not offer different settings for each tick depth
94 0 : return m_aLineProperties;
95 : }
96 :
97 0 : TickmarkProperties AxisProperties::makeTickmarkProperties(
98 : sal_Int32 nDepth ) const
99 : {
100 : /*
101 : nTickmarkStyle:
102 : 1: inner tickmarks
103 : 2: outer tickmarks
104 : 3: inner and outer tickmarks
105 : */
106 0 : sal_Int32 nTickmarkStyle = 1;
107 0 : if(nDepth==0)
108 : {
109 0 : nTickmarkStyle = m_nMajorTickmarks;
110 0 : if(!nTickmarkStyle)
111 : {
112 : //create major tickmarks as if they were minor tickmarks
113 0 : nDepth = 1;
114 0 : nTickmarkStyle = m_nMinorTickmarks;
115 : }
116 : }
117 0 : else if( nDepth==1)
118 : {
119 0 : nTickmarkStyle = m_nMinorTickmarks;
120 : }
121 :
122 0 : if( m_fInnerDirectionSign == 0.0 )
123 : {
124 0 : if( nTickmarkStyle != 0 )
125 0 : nTickmarkStyle = 3; //inner and outer tickmarks
126 : }
127 :
128 0 : TickmarkProperties aTickmarkProperties;
129 0 : aTickmarkProperties.Length = lcl_calcTickLengthForDepth(nDepth,nTickmarkStyle);
130 0 : aTickmarkProperties.RelativePos = static_cast<sal_Int32>(lcl_getTickOffset(aTickmarkProperties.Length,nTickmarkStyle));
131 0 : aTickmarkProperties.aLineProperties = this->makeLinePropertiesForDepth( nDepth );
132 0 : return aTickmarkProperties;
133 : }
134 :
135 0 : TickmarkProperties AxisProperties::makeTickmarkPropertiesForComplexCategories(
136 : sal_Int32 nTickLength, sal_Int32 nTickStartDistanceToAxis, sal_Int32 /*nTextLevel*/ ) const
137 : {
138 0 : sal_Int32 nTickmarkStyle = (m_fLabelDirectionSign==m_fInnerDirectionSign) ? 2/*outside*/ : 1/*inside*/;
139 :
140 0 : TickmarkProperties aTickmarkProperties;
141 0 : aTickmarkProperties.Length = nTickLength;// + nTextLevel*( lcl_calcTickLengthForDepth(0,nTickmarkStyle) );
142 0 : aTickmarkProperties.RelativePos = static_cast<sal_Int32>(lcl_getTickOffset(aTickmarkProperties.Length+nTickStartDistanceToAxis,nTickmarkStyle));
143 0 : aTickmarkProperties.aLineProperties = this->makeLinePropertiesForDepth( 0 );
144 0 : return aTickmarkProperties;
145 : }
146 :
147 0 : TickmarkProperties AxisProperties::getBiggestTickmarkProperties()
148 : {
149 0 : TickmarkProperties aTickmarkProperties;
150 0 : sal_Int32 nDepth = 0;
151 0 : sal_Int32 nTickmarkStyle = 3;//inner and outer tickmarks
152 0 : aTickmarkProperties.Length = lcl_calcTickLengthForDepth( nDepth,nTickmarkStyle );
153 0 : aTickmarkProperties.RelativePos = static_cast<sal_Int32>( lcl_getTickOffset( aTickmarkProperties.Length, nTickmarkStyle ) );
154 0 : return aTickmarkProperties;
155 : }
156 :
157 0 : AxisProperties::AxisProperties( const uno::Reference< XAxis >& xAxisModel
158 : , ExplicitCategoriesProvider* pExplicitCategoriesProvider )
159 : : m_xAxisModel(xAxisModel)
160 : , m_nDimensionIndex(0)
161 : , m_bIsMainAxis(true)
162 : , m_bSwapXAndY(false)
163 : , m_eCrossoverType( ::com::sun::star::chart::ChartAxisPosition_ZERO )
164 : , m_eLabelPos( ::com::sun::star::chart::ChartAxisLabelPosition_NEAR_AXIS )
165 : , m_eTickmarkPos( ::com::sun::star::chart::ChartAxisMarkPosition_AT_LABELS_AND_AXIS )
166 : , m_pfMainLinePositionAtOtherAxis(NULL)
167 : , m_pfExrtaLinePositionAtOtherAxis(NULL)
168 : , m_bCrossingAxisHasReverseDirection(false)
169 : , m_bCrossingAxisIsCategoryAxes(false)
170 : , m_fLabelDirectionSign(1.0)
171 : , m_fInnerDirectionSign(1.0)
172 : , m_aLabelAlignment(LABEL_ALIGN_RIGHT_TOP)
173 : , m_bDisplayLabels( true )
174 : , m_nNumberFormatKey(0)
175 : , m_nMajorTickmarks(1)
176 : , m_nMinorTickmarks(1)
177 : , m_aTickmarkPropertiesList()
178 : , m_aLineProperties()
179 : //for category axes
180 : , m_nAxisType(AxisType::REALNUMBER)
181 : , m_bComplexCategories(false)
182 : , m_pExplicitCategoriesProvider(pExplicitCategoriesProvider)
183 0 : , m_xAxisTextProvider(0)
184 : {
185 0 : }
186 :
187 0 : AxisProperties::AxisProperties( const AxisProperties& rAxisProperties )
188 : : m_xAxisModel( rAxisProperties.m_xAxisModel )
189 : , m_nDimensionIndex( rAxisProperties.m_nDimensionIndex )
190 : , m_bIsMainAxis( rAxisProperties.m_bIsMainAxis )
191 : , m_bSwapXAndY( rAxisProperties.m_bSwapXAndY )
192 : , m_eCrossoverType( rAxisProperties.m_eCrossoverType )
193 : , m_eLabelPos( rAxisProperties.m_eLabelPos )
194 : , m_eTickmarkPos( rAxisProperties.m_eTickmarkPos )
195 : , m_pfMainLinePositionAtOtherAxis( NULL )
196 : , m_pfExrtaLinePositionAtOtherAxis( NULL )
197 : , m_bCrossingAxisHasReverseDirection( rAxisProperties.m_bCrossingAxisHasReverseDirection )
198 : , m_bCrossingAxisIsCategoryAxes( rAxisProperties.m_bCrossingAxisIsCategoryAxes )
199 : , m_fLabelDirectionSign( rAxisProperties.m_fLabelDirectionSign )
200 : , m_fInnerDirectionSign( rAxisProperties.m_fInnerDirectionSign )
201 : , m_aLabelAlignment( rAxisProperties.m_aLabelAlignment )
202 : , m_bDisplayLabels( rAxisProperties.m_bDisplayLabels )
203 : , m_nNumberFormatKey( rAxisProperties.m_nNumberFormatKey )
204 : , m_nMajorTickmarks( rAxisProperties.m_nMajorTickmarks )
205 : , m_nMinorTickmarks( rAxisProperties.m_nMinorTickmarks )
206 : , m_aTickmarkPropertiesList( rAxisProperties.m_aTickmarkPropertiesList )
207 : , m_aLineProperties( rAxisProperties.m_aLineProperties )
208 : //for category axes
209 : , m_nAxisType( rAxisProperties.m_nAxisType )
210 : , m_bComplexCategories( rAxisProperties.m_bComplexCategories )
211 : , m_pExplicitCategoriesProvider( rAxisProperties.m_pExplicitCategoriesProvider )
212 0 : , m_xAxisTextProvider( rAxisProperties.m_xAxisTextProvider )
213 : {
214 0 : if( rAxisProperties.m_pfMainLinePositionAtOtherAxis )
215 0 : m_pfMainLinePositionAtOtherAxis = new double(*rAxisProperties.m_pfMainLinePositionAtOtherAxis);
216 0 : if( rAxisProperties.m_pfExrtaLinePositionAtOtherAxis )
217 0 : m_pfExrtaLinePositionAtOtherAxis = new double (*rAxisProperties.m_pfExrtaLinePositionAtOtherAxis);
218 0 : }
219 :
220 0 : AxisProperties::~AxisProperties()
221 : {
222 0 : delete m_pfMainLinePositionAtOtherAxis;
223 0 : delete m_pfExrtaLinePositionAtOtherAxis;
224 0 : }
225 :
226 0 : LabelAlignment lcl_getLabelAlignmentForZAxis( const AxisProperties& rAxisProperties )
227 : {
228 0 : LabelAlignment aRet( LABEL_ALIGN_RIGHT );
229 0 : if( rAxisProperties.m_fLabelDirectionSign<0 )
230 0 : aRet = LABEL_ALIGN_LEFT;
231 0 : return aRet;
232 : }
233 :
234 0 : LabelAlignment lcl_getLabelAlignmentForYAxis( const AxisProperties& rAxisProperties )
235 : {
236 0 : LabelAlignment aRet( LABEL_ALIGN_RIGHT );
237 0 : if( rAxisProperties.m_fLabelDirectionSign<0 )
238 0 : aRet = LABEL_ALIGN_LEFT;
239 0 : return aRet;
240 : }
241 :
242 0 : LabelAlignment lcl_getLabelAlignmentForXAxis( const AxisProperties& rAxisProperties )
243 : {
244 0 : LabelAlignment aRet( LABEL_ALIGN_BOTTOM );
245 0 : if( rAxisProperties.m_fLabelDirectionSign<0 )
246 0 : aRet = LABEL_ALIGN_TOP;
247 0 : return aRet;
248 : }
249 :
250 0 : void AxisProperties::initAxisPositioning( const uno::Reference< beans::XPropertySet >& xAxisProp )
251 : {
252 0 : if( !xAxisProp.is() )
253 0 : return;
254 : try
255 : {
256 0 : if( AxisHelper::isAxisPositioningEnabled() )
257 : {
258 0 : xAxisProp->getPropertyValue("CrossoverPosition") >>= m_eCrossoverType;
259 0 : if( ::com::sun::star::chart::ChartAxisPosition_VALUE == m_eCrossoverType )
260 : {
261 0 : double fValue = 0.0;
262 0 : xAxisProp->getPropertyValue("CrossoverValue") >>= fValue;
263 :
264 0 : if( m_bCrossingAxisIsCategoryAxes )
265 0 : fValue = ::rtl::math::round(fValue);
266 0 : m_pfMainLinePositionAtOtherAxis = new double(fValue);
267 : }
268 0 : else if( ::com::sun::star::chart::ChartAxisPosition_ZERO == m_eCrossoverType )
269 0 : m_pfMainLinePositionAtOtherAxis = new double(0.0);
270 :
271 0 : xAxisProp->getPropertyValue("LabelPosition") >>= m_eLabelPos;
272 0 : xAxisProp->getPropertyValue("MarkPosition") >>= m_eTickmarkPos;
273 : }
274 : else
275 : {
276 0 : m_eCrossoverType = ::com::sun::star::chart::ChartAxisPosition_START;
277 0 : if( m_bIsMainAxis == m_bCrossingAxisHasReverseDirection )
278 0 : m_eCrossoverType = ::com::sun::star::chart::ChartAxisPosition_END;
279 0 : m_eLabelPos = ::com::sun::star::chart::ChartAxisLabelPosition_NEAR_AXIS;
280 0 : m_eTickmarkPos = ::com::sun::star::chart::ChartAxisMarkPosition_AT_LABELS;
281 : }
282 : }
283 0 : catch( const uno::Exception& e )
284 : {
285 : ASSERT_EXCEPTION( e );
286 : }
287 : }
288 :
289 0 : void AxisProperties::init( bool bCartesian )
290 : {
291 : uno::Reference< beans::XPropertySet > xProp =
292 0 : uno::Reference<beans::XPropertySet>::query( this->m_xAxisModel );
293 0 : if( !xProp.is() )
294 0 : return;
295 :
296 0 : if( m_nDimensionIndex<2 )
297 0 : initAxisPositioning( xProp );
298 :
299 0 : ScaleData aScaleData = m_xAxisModel->getScaleData();
300 0 : if( m_nDimensionIndex==0 )
301 0 : AxisHelper::checkDateAxis( aScaleData, m_pExplicitCategoriesProvider, bCartesian );
302 0 : m_nAxisType = aScaleData.AxisType;
303 :
304 0 : if( bCartesian )
305 : {
306 0 : if( m_nDimensionIndex == 0 && m_nAxisType == AxisType::CATEGORY
307 0 : && m_pExplicitCategoriesProvider && m_pExplicitCategoriesProvider->hasComplexCategories() )
308 0 : m_bComplexCategories = true;
309 :
310 0 : if( ::com::sun::star::chart::ChartAxisPosition_END == m_eCrossoverType )
311 0 : m_fInnerDirectionSign = m_bCrossingAxisHasReverseDirection ? 1 : -1;
312 : else
313 0 : m_fInnerDirectionSign = m_bCrossingAxisHasReverseDirection ? -1 : 1;
314 :
315 0 : if( ::com::sun::star::chart::ChartAxisLabelPosition_NEAR_AXIS == m_eLabelPos )
316 0 : m_fLabelDirectionSign = m_fInnerDirectionSign;
317 0 : else if( ::com::sun::star::chart::ChartAxisLabelPosition_NEAR_AXIS_OTHER_SIDE == m_eLabelPos )
318 0 : m_fLabelDirectionSign = -m_fInnerDirectionSign;
319 0 : else if( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_START == m_eLabelPos )
320 0 : m_fLabelDirectionSign = m_bCrossingAxisHasReverseDirection ? -1 : 1;
321 0 : else if( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_END == m_eLabelPos )
322 0 : m_fLabelDirectionSign = m_bCrossingAxisHasReverseDirection ? 1 : -1;
323 :
324 0 : if( m_nDimensionIndex==2 )
325 0 : m_aLabelAlignment = lcl_getLabelAlignmentForZAxis(*this);
326 : else
327 : {
328 0 : bool bIsYAxisPosition = (m_nDimensionIndex==1 && !m_bSwapXAndY)
329 0 : || (m_nDimensionIndex==0 && m_bSwapXAndY);
330 0 : if( bIsYAxisPosition )
331 : {
332 0 : m_fLabelDirectionSign*=-1;
333 0 : m_fInnerDirectionSign*=-1;
334 : }
335 :
336 0 : if( bIsYAxisPosition )
337 0 : m_aLabelAlignment = lcl_getLabelAlignmentForYAxis(*this);
338 : else
339 0 : m_aLabelAlignment = lcl_getLabelAlignmentForXAxis(*this);
340 : }
341 : }
342 :
343 : try
344 : {
345 : //init LineProperties
346 0 : m_aLineProperties.initFromPropertySet( xProp );
347 :
348 : //init display labels
349 0 : xProp->getPropertyValue( "DisplayLabels" ) >>= m_bDisplayLabels;
350 :
351 : //init TickmarkProperties
352 0 : xProp->getPropertyValue( "MajorTickmarks" ) >>= m_nMajorTickmarks;
353 0 : xProp->getPropertyValue( "MinorTickmarks" ) >>= m_nMinorTickmarks;
354 :
355 0 : sal_Int32 nMaxDepth = 0;
356 0 : if(m_nMinorTickmarks!=0)
357 0 : nMaxDepth=2;
358 0 : else if(m_nMajorTickmarks!=0)
359 0 : nMaxDepth=1;
360 :
361 0 : this->m_aTickmarkPropertiesList.clear();
362 0 : for( sal_Int32 nDepth=0; nDepth<nMaxDepth; nDepth++ )
363 : {
364 0 : TickmarkProperties aTickmarkProperties = this->makeTickmarkProperties( nDepth );
365 0 : this->m_aTickmarkPropertiesList.push_back( aTickmarkProperties );
366 0 : }
367 : }
368 0 : catch( const uno::Exception& e )
369 : {
370 : ASSERT_EXCEPTION( e );
371 0 : }
372 : }
373 :
374 0 : AxisLabelProperties::AxisLabelProperties()
375 : : m_aFontReferenceSize( ChartModelHelper::getDefaultPageSize() )
376 : , m_aMaximumSpaceForLabels( 0 , 0, m_aFontReferenceSize.Width, m_aFontReferenceSize.Height )
377 : , nNumberFormatKey(0)
378 : , eStaggering( SIDE_BY_SIDE )
379 : , bLineBreakAllowed( false )
380 : , bOverlapAllowed( false )
381 : , bStackCharacters( false )
382 : , fRotationAngleDegree( 0.0 )
383 : , nRhythm( 1 )
384 0 : , bRhythmIsFix(false)
385 : {
386 :
387 0 : }
388 :
389 0 : void AxisLabelProperties::init( const uno::Reference< XAxis >& xAxisModel )
390 : {
391 : uno::Reference< beans::XPropertySet > xProp =
392 0 : uno::Reference<beans::XPropertySet>::query( xAxisModel );
393 0 : if(xProp.is())
394 : {
395 : try
396 : {
397 0 : xProp->getPropertyValue( "TextBreak" ) >>= this->bLineBreakAllowed;
398 0 : xProp->getPropertyValue( "TextOverlap" ) >>= this->bOverlapAllowed;
399 0 : xProp->getPropertyValue( "StackCharacters" ) >>= this->bStackCharacters;
400 0 : xProp->getPropertyValue( "TextRotation" ) >>= this->fRotationAngleDegree;
401 :
402 : ::com::sun::star::chart::ChartAxisArrangeOrderType eArrangeOrder;
403 0 : xProp->getPropertyValue( "ArrangeOrder" ) >>= eArrangeOrder;
404 0 : switch(eArrangeOrder)
405 : {
406 : case ::com::sun::star::chart::ChartAxisArrangeOrderType_SIDE_BY_SIDE:
407 0 : this->eStaggering = SIDE_BY_SIDE;
408 0 : break;
409 : case ::com::sun::star::chart::ChartAxisArrangeOrderType_STAGGER_EVEN:
410 0 : this->eStaggering = STAGGER_EVEN;
411 0 : break;
412 : case ::com::sun::star::chart::ChartAxisArrangeOrderType_STAGGER_ODD:
413 0 : this->eStaggering = STAGGER_ODD;
414 0 : break;
415 : default:
416 0 : this->eStaggering = STAGGER_AUTO;
417 0 : break;
418 : }
419 : }
420 0 : catch( const uno::Exception& e )
421 : {
422 : ASSERT_EXCEPTION( e );
423 : }
424 0 : }
425 0 : }
426 :
427 0 : bool AxisLabelProperties::getIsStaggered() const
428 : {
429 0 : return ( STAGGER_ODD == eStaggering || STAGGER_EVEN == eStaggering );
430 : }
431 :
432 : } //namespace chart
433 :
434 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|