Branch data 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 <basegfx/numeric/ftools.hxx>
21 : :
22 : : #include "VCartesianAxis.hxx"
23 : : #include "PlottingPositionHelper.hxx"
24 : : #include "ShapeFactory.hxx"
25 : : #include "CommonConverters.hxx"
26 : : #include "macros.hxx"
27 : : #include "ViewDefines.hxx"
28 : : #include "PropertyMapper.hxx"
29 : : #include "NumberFormatterWrapper.hxx"
30 : : #include "LabelPositionHelper.hxx"
31 : : #include "TrueGuard.hxx"
32 : : #include "BaseGFXHelper.hxx"
33 : : #include "AxisHelper.hxx"
34 : : #include "Tickmarks_Equidistant.hxx"
35 : :
36 : : #include <rtl/math.hxx>
37 : : #include <tools/color.hxx>
38 : : #include <com/sun/star/text/XText.hpp>
39 : : #include <com/sun/star/text/WritingMode2.hpp>
40 : : #include <editeng/unoprnms.hxx>
41 : : #include <svx/unoshape.hxx>
42 : : #include <svx/unoshtxt.hxx>
43 : :
44 : : #include <algorithm>
45 : : #include <boost/scoped_ptr.hpp>
46 : :
47 : : //.............................................................................
48 : : namespace chart
49 : : {
50 : : //.............................................................................
51 : : using namespace ::com::sun::star;
52 : : using namespace ::com::sun::star::chart2;
53 : : using namespace ::rtl::math;
54 : : using ::com::sun::star::uno::Reference;
55 : :
56 : : //-----------------------------------------------------------------------------
57 : : //-----------------------------------------------------------------------------
58 : : //-----------------------------------------------------------------------------
59 : :
60 : 1938 : VCartesianAxis::VCartesianAxis( const AxisProperties& rAxisProperties
61 : : , const Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier
62 : : , sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount
63 : : , PlottingPositionHelper* pPosHelper )//takes ownership
64 : 1938 : : VAxisBase( nDimensionIndex, nDimensionCount, rAxisProperties, xNumberFormatsSupplier )
65 : : {
66 [ - + ]: 1938 : if( pPosHelper )
67 : 0 : m_pPosHelper = pPosHelper;
68 : : else
69 [ + - ][ + - ]: 1938 : m_pPosHelper = new PlottingPositionHelper();
70 : 1938 : }
71 : :
72 : 1938 : VCartesianAxis::~VCartesianAxis()
73 : : {
74 [ + - ][ + - ]: 1938 : delete m_pPosHelper;
75 : 1938 : m_pPosHelper = NULL;
76 [ - + ]: 3876 : }
77 : :
78 : : //-----------------------------------------------------------------------------
79 : : //-----------------------------------------------------------------------------
80 : :
81 : 15951 : Reference< drawing::XShape > createSingleLabel(
82 : : const Reference< lang::XMultiServiceFactory>& xShapeFactory
83 : : , const Reference< drawing::XShapes >& xTarget
84 : : , const awt::Point& rAnchorScreenPosition2D
85 : : , const rtl::OUString& rLabel
86 : : , const AxisLabelProperties& rAxisLabelProperties
87 : : , const AxisProperties& rAxisProperties
88 : : , const tNameSequence& rPropNames
89 : : , const tAnySequence& rPropValues
90 : : )
91 : : {
92 [ + + ]: 15951 : if(rLabel.isEmpty())
93 [ + - ]: 18 : return 0;
94 : :
95 : : // #i78696# use mathematically correct rotation now
96 : 15933 : const double fRotationAnglePi(rAxisLabelProperties.fRotationAngleDegree * (F_PI / -180.0));
97 [ + - ]: 15933 : uno::Any aATransformation = ShapeFactory::makeTransformation( rAnchorScreenPosition2D, fRotationAnglePi );
98 [ + - ]: 15933 : rtl::OUString aLabel = ShapeFactory::getStackedString( rLabel, rAxisLabelProperties.bStackCharacters );
99 : :
100 : : Reference< drawing::XShape > xShape2DText = ShapeFactory(xShapeFactory)
101 [ + - ][ + - ]: 15933 : .createText( xTarget, aLabel, rPropNames, rPropValues, aATransformation );
[ + - ]
102 : :
103 : : //correctPositionForRotation
104 : : LabelPositionHelper::correctPositionForRotation( xShape2DText
105 [ + - ]: 15933 : , rAxisProperties.m_aLabelAlignment, rAxisLabelProperties.fRotationAngleDegree, rAxisProperties.m_bComplexCategories );
106 : :
107 : 15951 : return xShape2DText;
108 : : }
109 : :
110 : 7531 : bool lcl_doesShapeOverlapWithTickmark( const Reference< drawing::XShape >& xShape
111 : : , double fRotationAngleDegree
112 : : , const basegfx::B2DVector& rTickScreenPosition
113 : : , bool bIsHorizontalAxis, bool bIsVerticalAxis )
114 : : {
115 [ - + ]: 7531 : if(!xShape.is())
116 : 0 : return false;
117 : :
118 [ + - ][ + - ]: 7531 : ::basegfx::B2IRectangle aShapeRect = BaseGFXHelper::makeRectangle(xShape->getPosition(),ShapeFactory::getSizeAfterRotation( xShape, fRotationAngleDegree ));
[ + - ][ + - ]
119 : :
120 [ + + ]: 7531 : if( bIsVerticalAxis )
121 : : {
122 [ + - ]: 4170 : return ( (rTickScreenPosition.getY() >= aShapeRect.getMinY())
123 [ + + ][ + - ]: 4170 : && (rTickScreenPosition.getY() <= aShapeRect.getMaxY()) );
[ + - ]
124 : : }
125 [ + + ]: 3361 : if( bIsHorizontalAxis )
126 : : {
127 [ + - ]: 3304 : return ( (rTickScreenPosition.getX() >= aShapeRect.getMinX())
128 [ + - ][ + - ]: 3304 : && (rTickScreenPosition.getX() <= aShapeRect.getMaxX()) );
[ - + ]
129 : : }
130 : :
131 : : basegfx::B2IVector aPosition(
132 : 57 : static_cast<sal_Int32>( rTickScreenPosition.getX() )
133 : 114 : , static_cast<sal_Int32>( rTickScreenPosition.getY() ) );
134 [ + - ]: 7531 : return aShapeRect.isInside(aPosition);
135 : : }
136 : :
137 : 7489 : bool doesOverlap( const Reference< drawing::XShape >& xShape1
138 : : , const Reference< drawing::XShape >& xShape2
139 : : , double fRotationAngleDegree )
140 : : {
141 [ + - ][ - + ]: 7489 : if( !xShape1.is() || !xShape2.is() )
[ - + ]
142 : 0 : return false;
143 : :
144 [ + - ][ + - ]: 7489 : ::basegfx::B2IRectangle aRect1( BaseGFXHelper::makeRectangle(xShape1->getPosition(),ShapeFactory::getSizeAfterRotation( xShape1, fRotationAngleDegree )));
[ + - ][ + - ]
145 [ + - ][ + - ]: 7489 : ::basegfx::B2IRectangle aRect2( BaseGFXHelper::makeRectangle(xShape2->getPosition(),ShapeFactory::getSizeAfterRotation( xShape2, fRotationAngleDegree )));
[ + - ][ + - ]
146 [ + - ]: 7489 : return aRect1.overlaps(aRect2);
147 : : }
148 : :
149 : 58 : void removeShapesAtWrongRhythm( TickIter& rIter
150 : : , sal_Int32 nCorrectRhythm
151 : : , sal_Int32 nMaxTickToCheck
152 : : , const Reference< drawing::XShapes >& xTarget )
153 : : {
154 : 58 : sal_Int32 nTick = 0;
155 [ + + ][ + + ]: 223 : for( TickInfo* pTickInfo = rIter.firstInfo()
[ + + ]
156 : : ; pTickInfo && nTick <= nMaxTickToCheck
157 : 165 : ; pTickInfo = rIter.nextInfo(), nTick++ )
158 : : {
159 : : //remove labels which does not fit into the rhythm
160 [ + + ]: 165 : if( nTick%nCorrectRhythm != 0)
161 : : {
162 [ + + ]: 99 : if(pTickInfo->xTextShape.is())
163 : : {
164 : 24 : xTarget->remove(pTickInfo->xTextShape);
165 : 24 : pTickInfo->xTextShape = NULL;
166 : : }
167 : : }
168 : : }
169 : 58 : }
170 : :
171 [ + - ][ - + ]: 1784 : class LabelIterator : public TickIter
172 : : {
173 : : //this Iterator iterates over existing text labels
174 : :
175 : : //if the labels are staggered and bInnerLine is true
176 : : //we iterate only through the labels which are lying more inside the diagram
177 : :
178 : : //if the labels are staggered and bInnerLine is false
179 : : //we iterate only through the labels which are lying more outside the diagram
180 : :
181 : : //if the labels are not staggered
182 : : //we iterate through all labels
183 : :
184 : : public:
185 : : LabelIterator( ::std::vector< TickInfo >& rTickInfoVector
186 : : , const AxisLabelStaggering eAxisLabelStaggering
187 : : , bool bInnerLine );
188 : :
189 : : virtual TickInfo* firstInfo();
190 : : virtual TickInfo* nextInfo();
191 : :
192 : : private: //methods
193 : : LabelIterator();
194 : :
195 : : private: //member
196 : : PureTickIter m_aPureTickIter;
197 : : const AxisLabelStaggering m_eAxisLabelStaggering;
198 : : bool m_bInnerLine;
199 : : };
200 : :
201 : 1784 : LabelIterator::LabelIterator( ::std::vector< TickInfo >& rTickInfoVector
202 : : , const AxisLabelStaggering eAxisLabelStaggering
203 : : , bool bInnerLine )
204 : : : m_aPureTickIter( rTickInfoVector )
205 : : , m_eAxisLabelStaggering(eAxisLabelStaggering)
206 [ + - ]: 1784 : , m_bInnerLine(bInnerLine)
207 : : {
208 : 1784 : }
209 : :
210 : 1781 : TickInfo* LabelIterator::firstInfo()
211 : : {
212 : 1781 : TickInfo* pTickInfo = m_aPureTickIter.firstInfo();
213 [ + + ][ + + ]: 1791 : while( pTickInfo && !pTickInfo->xTextShape.is() )
[ + + ]
214 : 10 : pTickInfo = m_aPureTickIter.nextInfo();
215 [ + + ]: 1781 : if(!pTickInfo)
216 : 2 : return NULL;
217 [ + - ][ + + ]: 1779 : if( (STAGGER_EVEN==m_eAxisLabelStaggering && m_bInnerLine)
[ - + ][ # # ]
218 : : ||
219 : 0 : (STAGGER_ODD==m_eAxisLabelStaggering && !m_bInnerLine)
220 : : )
221 : : {
222 : : //skip first label
223 [ + + ]: 1811 : do
[ + + + + ]
224 : 906 : pTickInfo = m_aPureTickIter.nextInfo();
225 : 905 : while( pTickInfo && !pTickInfo->xTextShape.is() );
226 : : }
227 [ + + ]: 1779 : if(!pTickInfo)
228 : 1 : return NULL;
229 : 1781 : return pTickInfo;
230 : : }
231 : :
232 : 3585 : TickInfo* LabelIterator::nextInfo()
233 : : {
234 : 3585 : TickInfo* pTickInfo = NULL;
235 : : //get next label
236 [ + + ]: 7401 : do
[ + + + + ]
237 : 4145 : pTickInfo = m_aPureTickIter.nextInfo();
238 : 3256 : while( pTickInfo && !pTickInfo->xTextShape.is() );
239 : :
240 [ - + ][ # # ]: 3585 : if( STAGGER_EVEN==m_eAxisLabelStaggering
241 : : || STAGGER_ODD==m_eAxisLabelStaggering )
242 : : {
243 : : //skip one label
244 [ + + ]: 6480 : do
[ + + + + ]
245 : 4129 : pTickInfo = m_aPureTickIter.nextInfo();
246 : 2351 : while( pTickInfo && !pTickInfo->xTextShape.is() );
247 : : }
248 : 3585 : return pTickInfo;
249 : : }
250 : :
251 : 892 : B2DVector lcl_getLabelsDistance( TickIter& rIter, const B2DVector& rDistanceTickToText, double fRotationAngleDegree )
252 : : {
253 : : //calculates the height or width of a line of labels
254 : : //thus a following line of labels can be shifted for that distance
255 : :
256 : 892 : B2DVector aRet(0,0);
257 : :
258 [ + - ]: 892 : sal_Int32 nDistanceTickToText = static_cast<sal_Int32>( rDistanceTickToText.getLength() );
259 [ + - ]: 892 : if( nDistanceTickToText==0.0)
260 : : return aRet;
261 : :
262 : 892 : B2DVector aStaggerDirection(rDistanceTickToText);
263 [ + - ]: 892 : aStaggerDirection.normalize();
264 : :
265 : 892 : sal_Int32 nDistance=0;
266 [ + - ]: 892 : Reference< drawing::XShape > xShape2DText(NULL);
267 [ + - ][ + - ]: 2670 : for( TickInfo* pTickInfo = rIter.firstInfo()
[ + + ]
268 : : ; pTickInfo
269 : 1778 : ; pTickInfo = rIter.nextInfo() )
270 : : {
271 [ + - ]: 1778 : xShape2DText = pTickInfo->xTextShape;
272 [ + - ]: 1778 : if( xShape2DText.is() )
273 : : {
274 [ + - ]: 1778 : awt::Size aSize = ShapeFactory::getSizeAfterRotation( xShape2DText, fRotationAngleDegree );
275 [ + + ]: 1778 : if(fabs(aStaggerDirection.getX())>fabs(aStaggerDirection.getY()))
276 [ + - ]: 101 : nDistance = ::std::max(nDistance,aSize.Width);
277 : : else
278 [ + - ]: 1778 : nDistance = ::std::max(nDistance,aSize.Height);
279 : : }
280 : : }
281 : :
282 [ + - ]: 892 : aRet = aStaggerDirection*nDistance;
283 : :
284 : : //add extra distance for vertical distance
285 [ + + ]: 892 : if(fabs(aStaggerDirection.getX())>fabs(aStaggerDirection.getY()))
286 : 36 : aRet += rDistanceTickToText;
287 : :
288 : 892 : return aRet;
289 : : }
290 : :
291 : 892 : void lcl_shiftLables( TickIter& rIter, const B2DVector& rStaggerDistance )
292 : : {
293 [ + - ][ + + ]: 892 : if(rStaggerDistance.getLength()==0.0)
294 : 892 : return;
295 [ + - ]: 889 : Reference< drawing::XShape > xShape2DText(NULL);
296 [ + - ][ + - ]: 2696 : for( TickInfo* pTickInfo = rIter.firstInfo()
[ + + ]
297 : : ; pTickInfo
298 : 1807 : ; pTickInfo = rIter.nextInfo() )
299 : : {
300 [ + - ]: 1807 : xShape2DText = pTickInfo->xTextShape;
301 [ + - ]: 1807 : if( xShape2DText.is() )
302 : : {
303 [ + - ][ + - ]: 1807 : awt::Point aPos = xShape2DText->getPosition();
304 : 1807 : aPos.X += static_cast<sal_Int32>(rStaggerDistance.getX());
305 : 1807 : aPos.Y += static_cast<sal_Int32>(rStaggerDistance.getY());
306 [ + - ][ + - ]: 1807 : xShape2DText->setPosition( aPos );
307 : : }
308 : 892 : }
309 : : }
310 : :
311 : 0 : bool lcl_hasWordBreak( const Reference< drawing::XShape >& rxShape )
312 : : {
313 [ # # ]: 0 : if ( rxShape.is() )
314 : : {
315 : 0 : SvxShape* pShape = SvxShape::getImplementation( rxShape );
316 [ # # ]: 0 : SvxShapeText* pShapeText = dynamic_cast< SvxShapeText* >( pShape );
317 [ # # ]: 0 : if ( pShapeText )
318 : : {
319 [ # # ]: 0 : SvxTextEditSource* pTextEditSource = dynamic_cast< SvxTextEditSource* >( pShapeText->GetEditSource() );
320 [ # # ]: 0 : if ( pTextEditSource )
321 : : {
322 : 0 : pTextEditSource->UpdateOutliner();
323 : 0 : SvxTextForwarder* pTextForwarder = pTextEditSource->GetTextForwarder();
324 [ # # ]: 0 : if ( pTextForwarder )
325 : : {
326 : 0 : sal_uInt16 nParaCount = pTextForwarder->GetParagraphCount();
327 [ # # ]: 0 : for ( sal_uInt16 nPara = 0; nPara < nParaCount; ++nPara )
328 : : {
329 : 0 : sal_uInt16 nLineCount = pTextForwarder->GetLineCount( nPara );
330 [ # # ]: 0 : for ( sal_uInt16 nLine = 0; nLine < nLineCount; ++nLine )
331 : : {
332 : 0 : sal_uInt16 nLineStart = 0;
333 : 0 : sal_uInt16 nLineEnd = 0;
334 [ # # ]: 0 : pTextForwarder->GetLineBoundaries( nLineStart, nLineEnd, nPara, nLine );
335 : 0 : sal_uInt16 nWordStart = 0;
336 : 0 : sal_uInt16 nWordEnd = 0;
337 [ # # ][ # # ]: 0 : if ( pTextForwarder->GetWordIndices( nPara, nLineStart, nWordStart, nWordEnd ) &&
[ # # ][ # # ]
338 : : ( nWordStart != nLineStart ) )
339 : : {
340 : 0 : return true;
341 : : }
342 : : }
343 : : }
344 : : }
345 : : }
346 : : }
347 : : }
348 : :
349 : 0 : return false;
350 : : }
351 : :
352 : : class MaxLabelTickIter : public TickIter
353 : : {
354 : : //iterate over first two and last two labels and the longest label
355 : : public:
356 : : MaxLabelTickIter( ::std::vector< TickInfo >& rTickInfoVector
357 : : , sal_Int32 nLongestLabelIndex );
358 : : virtual ~MaxLabelTickIter();
359 : :
360 : : virtual TickInfo* firstInfo();
361 : : virtual TickInfo* nextInfo();
362 : :
363 : : private:
364 : : ::std::vector< TickInfo >& m_rTickInfoVector;
365 : : ::std::vector< sal_Int32 > m_aValidIndices;
366 : : sal_Int32 m_nCurrentIndex;
367 : : };
368 : :
369 : 1681 : MaxLabelTickIter::MaxLabelTickIter( ::std::vector< TickInfo >& rTickInfoVector
370 : : , sal_Int32 nLongestLabelIndex )
371 : : : m_rTickInfoVector(rTickInfoVector)
372 [ + - ]: 1681 : , m_nCurrentIndex(0)
373 : : {
374 : 1681 : sal_Int32 nMaxIndex = m_rTickInfoVector.size()-1;
375 [ + + ][ + - ]: 1681 : if( nLongestLabelIndex<0 || nLongestLabelIndex>=nMaxIndex-1 )
376 : 16 : nLongestLabelIndex = 0;
377 : :
378 [ + - ]: 1681 : if( nMaxIndex>=0 )
379 [ + - ]: 1681 : m_aValidIndices.push_back(0);
380 [ + + ]: 1681 : if( nMaxIndex>=1 )
381 [ + - ]: 1680 : m_aValidIndices.push_back(1);
382 [ - + ]: 1681 : if( nLongestLabelIndex>1 )
383 [ # # ]: 0 : m_aValidIndices.push_back(nLongestLabelIndex);
384 [ + + ]: 1681 : if( nMaxIndex > 2 )
385 [ + - ]: 1631 : m_aValidIndices.push_back(nMaxIndex-1);
386 [ + + ]: 1681 : if( nMaxIndex > 1 )
387 [ + - ]: 1668 : m_aValidIndices.push_back(nMaxIndex);
388 : 1681 : }
389 : 1681 : MaxLabelTickIter::~MaxLabelTickIter()
390 : : {
391 [ - + ]: 3362 : }
392 : :
393 : 1681 : TickInfo* MaxLabelTickIter::firstInfo()
394 : : {
395 : 1681 : m_nCurrentIndex = 0;
396 [ + - ]: 1681 : if( m_nCurrentIndex < static_cast<sal_Int32>(m_aValidIndices.size()) )
397 : 1681 : return &m_rTickInfoVector[m_aValidIndices[m_nCurrentIndex]];
398 : 1681 : return 0;
399 : : }
400 : :
401 : 6660 : TickInfo* MaxLabelTickIter::nextInfo()
402 : : {
403 : 6660 : m_nCurrentIndex++;
404 [ + - ][ + + ]: 6660 : if( m_nCurrentIndex>=0 && m_nCurrentIndex<static_cast<sal_Int32>(m_aValidIndices.size()) )
[ + + ]
405 : 4979 : return &m_rTickInfoVector[m_aValidIndices[m_nCurrentIndex]];
406 : 6660 : return 0;
407 : : }
408 : :
409 : 3420 : bool VCartesianAxis::isBreakOfLabelsAllowed( const AxisLabelProperties& rAxisLabelProperties
410 : : , bool bIsHorizontalAxis )
411 : : {
412 [ - + ]: 3420 : if( m_aTextLabels.getLength() > 100 )
413 : 0 : return false;
414 [ + + ]: 3420 : if( !rAxisLabelProperties.bLineBreakAllowed )
415 : 3303 : return false;
416 [ - + ]: 117 : if( rAxisLabelProperties.bStackCharacters )
417 : 0 : return false;
418 : : //no break for value axis
419 [ + + ]: 117 : if( !m_bUseTextLabels )
420 : 14 : return false;
421 [ + + ]: 103 : if( !::rtl::math::approxEqual( rAxisLabelProperties.fRotationAngleDegree, 0.0 ) )
422 : 3 : return false;
423 : : //break only for horizontal axis
424 : 3420 : return bIsHorizontalAxis;
425 : : }
426 : :
427 : 1731 : bool VCartesianAxis::isAutoStaggeringOfLabelsAllowed( const AxisLabelProperties& rAxisLabelProperties
428 : : , bool bIsHorizontalAxis, bool bIsVerticalAxis )
429 : : {
430 [ + + ]: 1731 : if( rAxisLabelProperties.eStaggering != STAGGER_AUTO )
431 : 215 : return false;
432 [ + + ]: 1516 : if( rAxisLabelProperties.bOverlapAllowed )
433 : 8 : return false;
434 [ - + ]: 1508 : if( rAxisLabelProperties.bLineBreakAllowed ) //auto line break or auto staggering, doing both automatisms they may conflict...
435 : 0 : return false;
436 [ - + ]: 1508 : if( !::rtl::math::approxEqual( rAxisLabelProperties.fRotationAngleDegree, 0.0 ) )
437 : 0 : return false;
438 : : //automatic staggering only for horizontal axis with horizontal text
439 : : //or vertical axis with vertical text
440 [ + + ]: 1508 : if( bIsHorizontalAxis )
441 : 856 : return !rAxisLabelProperties.bStackCharacters;
442 [ + + ]: 652 : if( bIsVerticalAxis )
443 : 637 : return rAxisLabelProperties.bStackCharacters;
444 : 1731 : return false;
445 : : }
446 : :
447 : : struct ComplexCategoryPlacement
448 : : {
449 : : rtl::OUString Text;
450 : : sal_Int32 Count;
451 : : double TickValue;
452 : :
453 : : ComplexCategoryPlacement( const rtl::OUString& rText, sal_Int32 nCount, double fTickValue )
454 : : : Text(rText), Count(nCount), TickValue(fTickValue)
455 : : {}
456 : : };
457 : :
458 : 0 : void VCartesianAxis::createAllTickInfosFromComplexCategories( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos, bool bShiftedPosition )
459 : : {
460 : : //no minor tickmarks will be generated!
461 : : //order is: inner labels first , outer labels last (that is different to all other TickIter cases)
462 [ # # ]: 0 : if(!bShiftedPosition)
463 : : {
464 : 0 : rAllTickInfos.clear();
465 : 0 : sal_Int32 nLevel=0;
466 : 0 : sal_Int32 nLevelCount = m_aAxisProperties.m_pExplicitCategoriesProvider->getCategoryLevelCount();
467 : 0 : sal_Int32 nCatIndex = 0;
468 [ # # ]: 0 : for( ; nLevel<nLevelCount; nLevel++ )
469 : : {
470 [ # # ]: 0 : ::std::vector< TickInfo > aTickInfoVector;
471 [ # # ]: 0 : std::vector< ComplexCategory > aComplexCategories( m_aAxisProperties.m_pExplicitCategoriesProvider->getCategoriesByLevel( nLevel ) );
472 [ # # ]: 0 : std::vector< ComplexCategory >::const_iterator aIt(aComplexCategories.begin());
473 [ # # ]: 0 : std::vector< ComplexCategory >::const_iterator aEnd(aComplexCategories.end());
474 [ # # ][ # # ]: 0 : for(;aIt!=aEnd;++aIt)
[ # # ]
475 : : {
476 [ # # ][ # # ]: 0 : TickInfo aTickInfo(0);
477 [ # # ][ # # ]: 0 : ComplexCategory aCat(*aIt);
478 : 0 : sal_Int32 nCount = aCat.Count;
479 [ # # ]: 0 : if( nCatIndex + 1.0 + nCount >= m_aScale.Maximum )
480 : : {
481 : 0 : nCount = static_cast<sal_Int32>(m_aScale.Maximum - 1.0 - nCatIndex);
482 [ # # ]: 0 : if( nCount <= 0 )
483 : 0 : nCount = 1;
484 : : }
485 : 0 : aTickInfo.fScaledTickValue = nCatIndex + 1.0 + nCount/2.0;
486 : 0 : aTickInfo.nFactorForLimitedTextWidth = nCount;
487 : 0 : aTickInfo.aText = aCat.Text;
488 [ # # ]: 0 : aTickInfoVector.push_back(aTickInfo);
489 : 0 : nCatIndex += nCount;
490 [ # # ]: 0 : if( nCatIndex + 1.0 >= m_aScale.Maximum )
491 : : break;
492 [ # # ][ # # ]: 0 : }
[ # # ][ # # ]
493 [ # # ]: 0 : rAllTickInfos.push_back(aTickInfoVector);
494 : 0 : }
495 : : }
496 : : else //bShiftedPosition==false
497 : : {
498 : 0 : rAllTickInfos.clear();
499 : 0 : sal_Int32 nLevel=0;
500 : 0 : sal_Int32 nLevelCount = m_aAxisProperties.m_pExplicitCategoriesProvider->getCategoryLevelCount();
501 [ # # ]: 0 : for( ; nLevel<nLevelCount; nLevel++ )
502 : : {
503 [ # # ]: 0 : ::std::vector< TickInfo > aTickInfoVector;
504 [ # # ]: 0 : std::vector< ComplexCategory > aComplexCategories( m_aAxisProperties.m_pExplicitCategoriesProvider->getCategoriesByLevel( nLevel ) );
505 : 0 : sal_Int32 nCatIndex = 0;
506 [ # # ]: 0 : std::vector< ComplexCategory >::const_iterator aIt(aComplexCategories.begin());
507 [ # # ]: 0 : std::vector< ComplexCategory >::const_iterator aEnd(aComplexCategories.end());
508 [ # # ][ # # ]: 0 : for(;aIt!=aEnd;++aIt)
[ # # ]
509 : : {
510 [ # # ][ # # ]: 0 : TickInfo aTickInfo(0);
511 [ # # ][ # # ]: 0 : ComplexCategory aCat(*aIt);
512 : 0 : aTickInfo.fScaledTickValue = nCatIndex + 1.0;
513 [ # # ]: 0 : aTickInfoVector.push_back(aTickInfo);
514 : 0 : nCatIndex += aCat.Count;
515 [ # # ]: 0 : if( nCatIndex + 1.0 > m_aScale.Maximum )
516 : : break;
517 [ # # ][ # # ]: 0 : }
[ # # ][ # # ]
518 : : //fill up with single ticks until maximum scale
519 [ # # ]: 0 : while( nCatIndex + 1.0 < m_aScale.Maximum )
520 : : {
521 [ # # ][ # # ]: 0 : TickInfo aTickInfo(0);
522 : 0 : aTickInfo.fScaledTickValue = nCatIndex + 1.0;
523 [ # # ]: 0 : aTickInfoVector.push_back(aTickInfo);
524 : 0 : nCatIndex ++;
525 [ # # ]: 0 : if( nLevel>0 )
526 : : break;
527 [ # # ][ # # ]: 0 : }
528 : : //add an additional tick at the end
529 : : {
530 [ # # ][ # # ]: 0 : TickInfo aTickInfo(0);
531 : 0 : aTickInfo.fScaledTickValue = m_aScale.Maximum;
532 [ # # ][ # # ]: 0 : aTickInfoVector.push_back(aTickInfo);
533 : : }
534 [ # # ]: 0 : rAllTickInfos.push_back(aTickInfoVector);
535 : 0 : }
536 : : }
537 : 0 : }
538 : :
539 : 3640 : void VCartesianAxis::createAllTickInfos( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos )
540 : : {
541 [ - + ]: 3640 : if( isComplexCategoryAxis() )
542 : 0 : createAllTickInfosFromComplexCategories( rAllTickInfos, false );
543 : : else
544 : 3640 : VAxisBase::createAllTickInfos(rAllTickInfos);
545 : 3640 : }
546 : :
547 : 1681 : TickIter* VCartesianAxis::createLabelTickIterator( sal_Int32 nTextLevel )
548 : : {
549 [ + - ][ + - ]: 1681 : if( nTextLevel>=0 && nTextLevel < static_cast< sal_Int32 >(m_aAllTickInfos.size()) )
[ + - ]
550 [ + - ]: 1681 : return new PureTickIter( m_aAllTickInfos[nTextLevel] );
551 : 1681 : return NULL;
552 : : }
553 : :
554 : 1681 : TickIter* VCartesianAxis::createMaximumLabelTickIterator( sal_Int32 nTextLevel )
555 : : {
556 [ + - ][ - + ]: 1681 : if( isComplexCategoryAxis() || isDateAxis() )
[ - + ]
557 : : {
558 : 0 : return createLabelTickIterator( nTextLevel ); //mmmm maybe todo: create less than all texts here
559 : : }
560 : : else
561 : : {
562 [ + - ]: 1681 : if(nTextLevel==0)
563 : : {
564 [ + - ]: 1681 : if( !m_aAllTickInfos.empty() )
565 : : {
566 [ + + ]: 1681 : sal_Int32 nLongestLabelIndex = m_bUseTextLabels ? this->getIndexOfLongestLabel( m_aTextLabels ) : 0;
567 [ + - ]: 1681 : return new MaxLabelTickIter( m_aAllTickInfos[0], nLongestLabelIndex );
568 : : }
569 : : }
570 : : }
571 : 1681 : return NULL;
572 : : }
573 : :
574 : 3362 : sal_Int32 VCartesianAxis::getTextLevelCount() const
575 : : {
576 : 3362 : sal_Int32 nTextLevelCount = 1;
577 [ - + ]: 3362 : if( isComplexCategoryAxis() )
578 : 0 : nTextLevelCount = m_aAxisProperties.m_pExplicitCategoriesProvider->getCategoryLevelCount();
579 : 3362 : return nTextLevelCount;
580 : : }
581 : :
582 : 3420 : bool VCartesianAxis::createTextShapes(
583 : : const Reference< drawing::XShapes >& xTarget
584 : : , TickIter& rTickIter
585 : : , AxisLabelProperties& rAxisLabelProperties
586 : : , TickFactory_2D* pTickFactory
587 : : , sal_Int32 nScreenDistanceBetweenTicks )
588 : : {
589 : : //returns true if the text shapes have been created successfully
590 : : //otherwise false - in this case the AxisLabelProperties have changed
591 : : //and contain new instructions for the next try for text shape creation
592 : :
593 [ + - ]: 3420 : Reference< XScaling > xInverseScaling( NULL );
594 [ + + ]: 3420 : if( m_aScale.Scaling.is() )
595 [ + - ][ + - ]: 1452 : xInverseScaling = m_aScale.Scaling->getInverseScaling();
[ + - ]
596 : :
597 : : FixedNumberFormatter aFixedNumberFormatter(
598 [ + - ]: 3420 : m_xNumberFormatsSupplier, rAxisLabelProperties.nNumberFormatKey );
599 : :
600 [ + - ]: 3420 : const bool bIsHorizontalAxis = pTickFactory->isHorizontalAxis();
601 [ + - ]: 3420 : const bool bIsVerticalAxis = pTickFactory->isVerticalAxis();
602 [ + - ]: 3420 : bool bIsStaggered = rAxisLabelProperties.getIsStaggered();
603 [ + - ]: 3420 : B2DVector aTextToTickDistance( pTickFactory->getDistanceAxisTickToText( m_aAxisProperties, true ) );
604 : 3420 : sal_Int32 nLimitedSpaceForText = -1;
605 [ + - ][ + + ]: 3420 : if( isBreakOfLabelsAllowed( rAxisLabelProperties, bIsHorizontalAxis ) )
606 : : {
607 : 100 : nLimitedSpaceForText = nScreenDistanceBetweenTicks;
608 [ - + ]: 100 : if( bIsStaggered )
609 : 0 : nLimitedSpaceForText *= 2;
610 : :
611 [ + - ]: 100 : if( nLimitedSpaceForText > 0 )
612 : : { //reduce space for a small amount to have a visible distance between the labels:
613 : 100 : sal_Int32 nReduce = (nLimitedSpaceForText*5)/100;
614 [ - + ]: 100 : if(!nReduce)
615 : 0 : nReduce = 1;
616 : 100 : nLimitedSpaceForText -= nReduce;
617 : : }
618 : : }
619 : :
620 : 3420 : uno::Sequence< rtl::OUString >* pCategories = 0;
621 [ + + ][ + - ]: 3420 : if( m_bUseTextLabels && !m_aAxisProperties.m_bComplexCategories )
622 : 1942 : pCategories = &m_aTextLabels;
623 : :
624 : 3420 : TickInfo* pPreviousVisibleTickInfo = NULL;
625 : 3420 : TickInfo* pPREPreviousVisibleTickInfo = NULL;
626 : 3420 : TickInfo* pLastVisibleNeighbourTickInfo = NULL;
627 : :
628 : : //------------------------------------------------
629 : : //prepare properties for multipropertyset-interface of shape
630 [ + - ]: 3420 : tNameSequence aPropNames;
631 [ + - ]: 3420 : tAnySequence aPropValues;
632 : :
633 : 3420 : bool bLimitedHeight = fabs(aTextToTickDistance.getX()) > fabs(aTextToTickDistance.getY());
634 [ + - ]: 3420 : Reference< beans::XPropertySet > xProps( m_aAxisProperties.m_xAxisModel, uno::UNO_QUERY );
635 : : PropertyMapper::getTextLabelMultiPropertyLists( xProps, aPropNames, aPropValues, false
636 [ + - ]: 3420 : , nLimitedSpaceForText, bLimitedHeight );
637 : : LabelPositionHelper::doDynamicFontResize( aPropValues, aPropNames, xProps
638 [ + - ]: 3420 : , m_aAxisLabelProperties.m_aFontReferenceSize );
639 [ + - ]: 3420 : LabelPositionHelper::changeTextAdjustment( aPropValues, aPropNames, m_aAxisProperties.m_aLabelAlignment );
640 : :
641 [ + - ][ + - ]: 3420 : uno::Any* pColorAny = PropertyMapper::getValuePointer(aPropValues,aPropNames,C2U("CharColor"));
642 : 3420 : sal_Int32 nColor = Color( COL_AUTO ).GetColor();
643 [ + - ]: 3420 : if(pColorAny)
644 : 3420 : *pColorAny >>= nColor;
645 : :
646 [ + - ]: 3420 : uno::Any* pLimitedSpaceAny = PropertyMapper::getValuePointerForLimitedSpace(aPropValues,aPropNames,bLimitedHeight);
647 : : //------------------------------------------------
648 : :
649 : 3420 : sal_Int32 nTick = 0;
650 [ + - ][ + - ]: 19520 : for( TickInfo* pTickInfo = rTickIter.firstInfo()
[ + + ]
651 : : ; pTickInfo
652 : 16100 : ; pTickInfo = rTickIter.nextInfo(), nTick++ )
653 : : {
654 : : pLastVisibleNeighbourTickInfo = bIsStaggered ?
655 [ + + ]: 16158 : pPREPreviousVisibleTickInfo : pPreviousVisibleTickInfo;
656 : :
657 : : //don't create labels which does not fit into the rhythm
658 [ + + ]: 16158 : if( nTick%rAxisLabelProperties.nRhythm != 0)
659 : 107 : continue;
660 : :
661 : : //don't create labels for invisible ticks
662 [ - + ]: 16051 : if( !pTickInfo->bPaintIt )
663 : 0 : continue;
664 : :
665 : : //if NO OVERLAP -> don't create labels where the tick overlaps
666 : : //with the text of the last neighbour tickmark
667 [ + + ][ + + ]: 16051 : if( pLastVisibleNeighbourTickInfo && !rAxisLabelProperties.bOverlapAllowed )
668 : : {
669 [ + - ][ + + ]: 7531 : if( lcl_doesShapeOverlapWithTickmark( pLastVisibleNeighbourTickInfo->xTextShape
670 : : , rAxisLabelProperties.fRotationAngleDegree
671 : : , pTickInfo->aTickScreenPosition
672 : 7531 : , bIsHorizontalAxis, bIsVerticalAxis ) )
673 : : {
674 : 42 : bool bOverlapAlsoAfterSwitchingOnAutoStaggering = true;
675 [ + + ][ - + ]: 42 : if( !bIsStaggered && isAutoStaggeringOfLabelsAllowed( rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis ) )
[ - + ]
676 : : {
677 : 0 : bIsStaggered = true;
678 : 0 : rAxisLabelProperties.eStaggering = STAGGER_EVEN;
679 : 0 : pLastVisibleNeighbourTickInfo = pPREPreviousVisibleTickInfo;
680 [ # # ][ # # ]: 0 : if( !pLastVisibleNeighbourTickInfo ||
[ # # ]
681 : : !lcl_doesShapeOverlapWithTickmark( pLastVisibleNeighbourTickInfo->xTextShape
682 : : , rAxisLabelProperties.fRotationAngleDegree
683 : : , pTickInfo->aTickScreenPosition
684 [ # # ]: 0 : , bIsHorizontalAxis, bIsVerticalAxis ) )
685 : 0 : bOverlapAlsoAfterSwitchingOnAutoStaggering = false;
686 : : }
687 [ + - ]: 42 : if( bOverlapAlsoAfterSwitchingOnAutoStaggering )
688 : : {
689 [ - + ]: 42 : if( rAxisLabelProperties.bRhythmIsFix )
690 : 0 : continue;
691 : 42 : rAxisLabelProperties.nRhythm++;
692 [ + - ]: 42 : removeShapesAtWrongRhythm( rTickIter, rAxisLabelProperties.nRhythm, nTick, xTarget );
693 : 42 : return false;
694 : : }
695 : : }
696 : : }
697 : :
698 : : //xxxxx pTickInfo->updateUnscaledValue( xInverseScaling );
699 : :
700 : 16009 : bool bHasExtraColor=false;
701 : 16009 : sal_Int32 nExtraColor=0;
702 : :
703 : 16009 : rtl::OUString aLabel;
704 [ + + ]: 16009 : if(pCategories)
705 : : {
706 [ + - ]: 8195 : sal_Int32 nIndex = static_cast< sal_Int32 >(pTickInfo->getUnscaledTickValue()) - 1; //first category (index 0) matches with real number 1.0
707 [ + - ][ + + ]: 8195 : if( nIndex>=0 && nIndex<pCategories->getLength() )
[ + + ]
708 [ + - ]: 8183 : aLabel = (*pCategories)[nIndex];
709 : : }
710 [ - + ]: 7814 : else if( m_aAxisProperties.m_bComplexCategories )
711 : : {
712 : 0 : aLabel = pTickInfo->aText;
713 : : }
714 : : else
715 [ + - ][ + - ]: 7814 : aLabel = aFixedNumberFormatter.getFormattedString( pTickInfo->getUnscaledTickValue(), nExtraColor, bHasExtraColor );
716 : :
717 [ + - ]: 16009 : if(pColorAny)
718 [ - + ][ + - ]: 16009 : *pColorAny = uno::makeAny(bHasExtraColor?nExtraColor:nColor);
719 [ + + ]: 16009 : if(pLimitedSpaceAny)
720 [ + - ]: 400 : *pLimitedSpaceAny = uno::makeAny(sal_Int32(nLimitedSpaceForText*pTickInfo->nFactorForLimitedTextWidth));
721 : :
722 : 16009 : B2DVector aTickScreenPos2D( pTickInfo->aTickScreenPosition );
723 : 16009 : aTickScreenPos2D += aTextToTickDistance;
724 : : awt::Point aAnchorScreenPosition2D(
725 : 16009 : static_cast<sal_Int32>(aTickScreenPos2D.getX())
726 : 32018 : ,static_cast<sal_Int32>(aTickScreenPos2D.getY()));
727 : :
728 : : //create single label
729 [ + + ]: 16009 : if(!pTickInfo->xTextShape.is())
730 : : pTickInfo->xTextShape = createSingleLabel( m_xShapeFactory, xTarget
731 : : , aAnchorScreenPosition2D, aLabel
732 : : , rAxisLabelProperties, m_aAxisProperties
733 [ + - ][ + - ]: 15951 : , aPropNames, aPropValues );
734 [ + + ]: 16009 : if(!pTickInfo->xTextShape.is())
735 : 18 : continue;
736 : :
737 [ + - ]: 15991 : recordMaximumTextSize( pTickInfo->xTextShape, rAxisLabelProperties.fRotationAngleDegree );
738 : :
739 : : //better rotate if single words are broken apart
740 [ + + ]: 16391 : if( nLimitedSpaceForText>0 && !rAxisLabelProperties.bOverlapAllowed
[ + - + - ]
[ - + ][ # # ]
[ - + ]
741 : 400 : && ::rtl::math::approxEqual( rAxisLabelProperties.fRotationAngleDegree, 0.0 )
742 : : && m_aAxisProperties.m_bComplexCategories
743 [ # # ]: 0 : && lcl_hasWordBreak( pTickInfo->xTextShape ) )
744 : : {
745 : 0 : rAxisLabelProperties.fRotationAngleDegree = 90;
746 : 0 : rAxisLabelProperties.bLineBreakAllowed = false;
747 : 0 : m_aAxisLabelProperties.fRotationAngleDegree = rAxisLabelProperties.fRotationAngleDegree;
748 [ # # ]: 0 : removeTextShapesFromTicks();
749 : 0 : return false;
750 : : }
751 : :
752 : : //if NO OVERLAP -> remove overlapping shapes
753 [ + + ][ + + ]: 15991 : if( pLastVisibleNeighbourTickInfo && !rAxisLabelProperties.bOverlapAllowed )
754 : : {
755 [ + - ][ + + ]: 7489 : if( doesOverlap( pLastVisibleNeighbourTickInfo->xTextShape, pTickInfo->xTextShape, rAxisLabelProperties.fRotationAngleDegree ) )
756 : : {
757 : 16 : bool bOverlapAlsoAfterSwitchingOnAutoStaggering = true;
758 [ + - ][ - + ]: 16 : if( !bIsStaggered && isAutoStaggeringOfLabelsAllowed( rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis ) )
[ - + ]
759 : : {
760 : 0 : bIsStaggered = true;
761 : 0 : rAxisLabelProperties.eStaggering = STAGGER_EVEN;
762 : 0 : pLastVisibleNeighbourTickInfo = pPREPreviousVisibleTickInfo;
763 [ # # ][ # # ]: 0 : if( !pLastVisibleNeighbourTickInfo ||
[ # # ]
764 : : !lcl_doesShapeOverlapWithTickmark( pLastVisibleNeighbourTickInfo->xTextShape
765 : : , rAxisLabelProperties.fRotationAngleDegree
766 : : , pTickInfo->aTickScreenPosition
767 [ # # ]: 0 : , bIsHorizontalAxis, bIsVerticalAxis ) )
768 : 0 : bOverlapAlsoAfterSwitchingOnAutoStaggering = false;
769 : : }
770 [ + - ]: 16 : if( bOverlapAlsoAfterSwitchingOnAutoStaggering )
771 : : {
772 [ - + ]: 16 : if( rAxisLabelProperties.bRhythmIsFix )
773 : : {
774 [ # # ][ # # ]: 0 : xTarget->remove(pTickInfo->xTextShape);
775 [ # # ]: 0 : pTickInfo->xTextShape = NULL;
776 : 0 : continue;
777 : : }
778 : 16 : rAxisLabelProperties.nRhythm++;
779 [ + - ]: 16 : removeShapesAtWrongRhythm( rTickIter, rAxisLabelProperties.nRhythm, nTick, xTarget );
780 : 16 : return false;
781 : : }
782 : : }
783 : : }
784 : :
785 : 15975 : pPREPreviousVisibleTickInfo = pPreviousVisibleTickInfo;
786 [ + + + ]: 31984 : pPreviousVisibleTickInfo = pTickInfo;
787 [ + + + ]: 32167 : }
788 [ + - ][ + - ]: 3420 : return true;
[ + - ]
789 : : }
790 : :
791 : 0 : drawing::PointSequenceSequence lcl_makePointSequence( B2DVector& rStart, B2DVector& rEnd )
792 : : {
793 : 0 : drawing::PointSequenceSequence aPoints(1);
794 [ # # ][ # # ]: 0 : aPoints[0].realloc(2);
795 [ # # ][ # # ]: 0 : aPoints[0][0].X = static_cast<sal_Int32>(rStart.getX());
796 [ # # ][ # # ]: 0 : aPoints[0][0].Y = static_cast<sal_Int32>(rStart.getY());
797 [ # # ][ # # ]: 0 : aPoints[0][1].X = static_cast<sal_Int32>(rEnd.getX());
798 [ # # ][ # # ]: 0 : aPoints[0][1].Y = static_cast<sal_Int32>(rEnd.getY());
799 : 0 : return aPoints;
800 : : }
801 : :
802 : 22282 : double VCartesianAxis::getLogicValueWhereMainLineCrossesOtherAxis() const
803 : : {
804 [ + + ]: 22282 : double fMin = (m_nDimensionIndex==1) ? m_pPosHelper->getLogicMinX() : m_pPosHelper->getLogicMinY();
805 [ + + ]: 22282 : double fMax = (m_nDimensionIndex==1) ? m_pPosHelper->getLogicMaxX() : m_pPosHelper->getLogicMaxY();
806 : :
807 : : double fCrossesOtherAxis;
808 [ + + ]: 22282 : if(m_aAxisProperties.m_pfMainLinePositionAtOtherAxis)
809 : 20706 : fCrossesOtherAxis = *m_aAxisProperties.m_pfMainLinePositionAtOtherAxis;
810 : : else
811 : : {
812 [ - + ]: 1576 : if( ::com::sun::star::chart::ChartAxisPosition_END == m_aAxisProperties.m_eCrossoverType )
813 : 0 : fCrossesOtherAxis = fMax;
814 : : else
815 : 1576 : fCrossesOtherAxis = fMin;
816 : : }
817 : 22282 : return fCrossesOtherAxis;
818 : : }
819 : :
820 : 10598 : double VCartesianAxis::getLogicValueWhereLabelLineCrossesOtherAxis() const
821 : : {
822 [ + + ]: 10598 : double fMin = (m_nDimensionIndex==1) ? m_pPosHelper->getLogicMinX() : m_pPosHelper->getLogicMinY();
823 [ + + ]: 10598 : double fMax = (m_nDimensionIndex==1) ? m_pPosHelper->getLogicMaxX() : m_pPosHelper->getLogicMaxY();
824 : :
825 : : double fCrossesOtherAxis;
826 [ + + ]: 10598 : if( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_START == m_aAxisProperties.m_eLabelPos )
827 : 600 : fCrossesOtherAxis = fMin;
828 [ - + ]: 9998 : else if( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_END == m_aAxisProperties.m_eLabelPos )
829 : 0 : fCrossesOtherAxis = fMax;
830 : : else
831 : 9998 : fCrossesOtherAxis = getLogicValueWhereMainLineCrossesOtherAxis();
832 : 10598 : return fCrossesOtherAxis;
833 : : }
834 : :
835 : 0 : bool VCartesianAxis::getLogicValueWhereExtraLineCrossesOtherAxis( double& fCrossesOtherAxis ) const
836 : : {
837 [ # # ]: 0 : if( !m_aAxisProperties.m_pfExrtaLinePositionAtOtherAxis )
838 : 0 : return false;
839 [ # # ]: 0 : double fMin = (m_nDimensionIndex==1) ? m_pPosHelper->getLogicMinX() : m_pPosHelper->getLogicMinY();
840 [ # # ]: 0 : double fMax = (m_nDimensionIndex==1) ? m_pPosHelper->getLogicMaxX() : m_pPosHelper->getLogicMaxY();
841 [ # # ][ # # ]: 0 : if( *m_aAxisProperties.m_pfExrtaLinePositionAtOtherAxis <= fMin
842 : : || *m_aAxisProperties.m_pfExrtaLinePositionAtOtherAxis >= fMax )
843 : 0 : return false;
844 : 0 : fCrossesOtherAxis = *m_aAxisProperties.m_pfExrtaLinePositionAtOtherAxis;
845 : 0 : return true;
846 : : }
847 : :
848 : 45764 : B2DVector VCartesianAxis::getScreenPosition( double fLogicX, double fLogicY, double fLogicZ ) const
849 : : {
850 : 45764 : B2DVector aRet(0,0);
851 : :
852 [ + - ]: 45764 : if( m_pPosHelper )
853 : : {
854 [ + - ]: 45764 : drawing::Position3D aScenePos = m_pPosHelper->transformLogicToScene( fLogicX, fLogicY, fLogicZ, true );
855 [ + + ]: 45764 : if(3==m_nDimension)
856 : : {
857 [ + - ][ + - ]: 1036 : if( m_xLogicTarget.is() && m_pPosHelper && m_pShapeFactory )
[ + - ][ + - ]
858 : : {
859 [ + - ]: 1036 : tPropertyNameMap aDummyPropertyNameMap;
860 : : Reference< drawing::XShape > xShape3DAnchor = m_pShapeFactory->createCube( m_xLogicTarget
861 [ + - ][ + - ]: 1036 : , aScenePos,drawing::Direction3D(1,1,1), 0, 0, aDummyPropertyNameMap);
862 [ + - ][ + - ]: 1036 : awt::Point a2DPos = xShape3DAnchor->getPosition(); //get 2D position from xShape3DAnchor
863 [ + - ][ + - ]: 1036 : m_xLogicTarget->remove(xShape3DAnchor);
864 : 1036 : aRet.setX( a2DPos.X );
865 : 1036 : aRet.setY( a2DPos.Y );
866 : : }
867 : : else
868 : : {
869 : : OSL_FAIL("cannot calculate scrren position in VCartesianAxis::getScreenPosition");
870 : : }
871 : : }
872 : : else
873 : : {
874 : 44728 : aRet.setX( aScenePos.PositionX );
875 : 45764 : aRet.setY( aScenePos.PositionY );
876 : : }
877 : : }
878 : :
879 : 45764 : return aRet;
880 : : }
881 : :
882 : 0 : VCartesianAxis::ScreenPosAndLogicPos VCartesianAxis::getScreenPosAndLogicPos( double fLogicX_, double fLogicY_, double fLogicZ_ ) const
883 : : {
884 : 0 : ScreenPosAndLogicPos aRet;
885 : 0 : aRet.fLogicX = fLogicX_;
886 : 0 : aRet.fLogicY = fLogicY_;
887 : 0 : aRet.fLogicZ = fLogicZ_;
888 [ # # ][ # # ]: 0 : aRet.aScreenPos = getScreenPosition( fLogicX_, fLogicY_, fLogicZ_ );
889 : 0 : return aRet;
890 : : }
891 : :
892 : : typedef ::std::vector< VCartesianAxis::ScreenPosAndLogicPos > tScreenPosAndLogicPosList;
893 : : struct lcl_LessXPos : ::std::binary_function< VCartesianAxis::ScreenPosAndLogicPos, VCartesianAxis::ScreenPosAndLogicPos, bool >
894 : : {
895 : 0 : inline bool operator() ( const VCartesianAxis::ScreenPosAndLogicPos& rPos1, const VCartesianAxis::ScreenPosAndLogicPos& rPos2 )
896 : : {
897 : 0 : return ( rPos1.aScreenPos.getX() < rPos2.aScreenPos.getX() );
898 : : }
899 : : };
900 : :
901 : : struct lcl_GreaterYPos : ::std::binary_function< VCartesianAxis::ScreenPosAndLogicPos, VCartesianAxis::ScreenPosAndLogicPos, bool >
902 : : {
903 : 0 : inline bool operator() ( const VCartesianAxis::ScreenPosAndLogicPos& rPos1, const VCartesianAxis::ScreenPosAndLogicPos& rPos2 )
904 : : {
905 : 0 : return ( rPos1.aScreenPos.getY() > rPos2.aScreenPos.getY() );
906 : : }
907 : : };
908 : :
909 : 22882 : void VCartesianAxis::get2DAxisMainLine( B2DVector& rStart, B2DVector& rEnd, double fCrossesOtherAxis )
910 : : {
911 : : //m_aAxisProperties might get updated and changed here because
912 : : // the label alignmant and inner direction sign depends exactly of the choice of the axis line position which is made here in this method
913 : :
914 : 22882 : double fMinX = m_pPosHelper->getLogicMinX();
915 : 22882 : double fMinY = m_pPosHelper->getLogicMinY();
916 : 22882 : double fMinZ = m_pPosHelper->getLogicMinZ();
917 : 22882 : double fMaxX = m_pPosHelper->getLogicMaxX();
918 : 22882 : double fMaxY = m_pPosHelper->getLogicMaxY();
919 : 22882 : double fMaxZ = m_pPosHelper->getLogicMaxZ();
920 : :
921 : 22882 : double fXStart = fMinX;
922 : 22882 : double fYStart = fMinY;
923 : 22882 : double fZStart = fMinZ;
924 : 22882 : double fXEnd = fXStart;
925 : 22882 : double fYEnd = fYStart;
926 : 22882 : double fZEnd = fZStart;
927 : :
928 : 22882 : double fXOnXPlane = fMinX;
929 : 22882 : double fXOther = fMaxX;
930 [ - + ]: 22882 : int nDifferentValue = !m_pPosHelper->isMathematicalOrientationX() ? -1 : 1;
931 [ + + ]: 22882 : if( !m_pPosHelper->isSwapXAndY() )
932 [ - + ]: 22740 : nDifferentValue *= (CuboidPlanePosition_Left != m_eLeftWallPos) ? -1 : 1;
933 : : else
934 [ - + ]: 142 : nDifferentValue *= (CuboidPlanePosition_Bottom != m_eBottomPos) ? -1 : 1;
935 [ - + ]: 22882 : if( nDifferentValue<0 )
936 : : {
937 : 0 : fXOnXPlane = fMaxX;
938 : 0 : fXOther = fMinX;
939 : : }
940 : :
941 : 22882 : double fYOnYPlane = fMinY;
942 : 22882 : double fYOther = fMaxY;
943 [ + + ]: 22882 : nDifferentValue = !m_pPosHelper->isMathematicalOrientationY() ? -1 : 1;
944 [ + + ]: 22882 : if( !m_pPosHelper->isSwapXAndY() )
945 [ - + ]: 22740 : nDifferentValue *= (CuboidPlanePosition_Bottom != m_eBottomPos) ? -1 : 1;
946 : : else
947 [ - + ]: 142 : nDifferentValue *= (CuboidPlanePosition_Left != m_eLeftWallPos) ? -1 : 1;
948 [ + + ]: 22882 : if( nDifferentValue<0 )
949 : : {
950 : 1115 : fYOnYPlane = fMaxY;
951 : 1115 : fYOther = fMinY;
952 : : }
953 : :
954 : 22882 : double fZOnZPlane = fMaxZ;
955 : 22882 : double fZOther = fMinZ;
956 [ - + ]: 22882 : nDifferentValue = !m_pPosHelper->isMathematicalOrientationZ() ? -1 : 1;
957 [ - + ]: 22882 : nDifferentValue *= (CuboidPlanePosition_Back != m_eBackWallPos) ? -1 : 1;
958 [ - + ]: 22882 : if( nDifferentValue<0 )
959 : : {
960 : 0 : fZOnZPlane = fMinZ;
961 : 0 : fZOther = fMaxZ;
962 : : }
963 : :
964 [ + + ]: 22882 : if( 0==m_nDimensionIndex ) //x-axis
965 : : {
966 [ + + ]: 12504 : if( fCrossesOtherAxis < fMinY )
967 : 2964 : fCrossesOtherAxis = fMinY;
968 [ - + ]: 9540 : else if( fCrossesOtherAxis > fMaxY )
969 : 0 : fCrossesOtherAxis = fMaxY;
970 : :
971 : 12504 : fYStart = fYEnd = fCrossesOtherAxis;
972 : 12504 : fXEnd=m_pPosHelper->getLogicMaxX();
973 : :
974 [ + + ]: 12504 : if(3==m_nDimension)
975 : : {
976 [ + - ]: 182 : if( AxisHelper::isAxisPositioningEnabled() )
977 : : {
978 [ - + ]: 182 : if( ::rtl::math::approxEqual( fYOther, fYStart) )
979 : 0 : fZStart = fZEnd = fZOnZPlane;
980 : : else
981 : 182 : fZStart = fZEnd = fZOther;
982 : : }
983 : : else
984 : : {
985 [ # # ][ # # ]: 0 : rStart = getScreenPosition( fXStart, fYStart, fZStart );
986 [ # # ][ # # ]: 0 : rEnd = getScreenPosition( fXEnd, fYEnd, fZEnd );
987 : :
988 : 0 : double fDeltaX = rEnd.getX() - rStart.getX();
989 : 0 : double fDeltaY = rEnd.getY() - rStart.getY();
990 : :
991 : : //only those points are candidates which are lying on exactly one wall as these are outer edges
992 [ # # ]: 0 : tScreenPosAndLogicPosList aPosList;
993 [ # # ][ # # ]: 0 : aPosList.push_back( getScreenPosAndLogicPos( fMinX, fYOnYPlane, fZOther ) );
994 [ # # ][ # # ]: 0 : aPosList.push_back( getScreenPosAndLogicPos( fMinX, fYOther, fZOnZPlane ) );
995 : :
996 [ # # ]: 0 : if( fabs(fDeltaY) > fabs(fDeltaX) )
997 : : {
998 : 0 : m_aAxisProperties.m_aLabelAlignment = LABEL_ALIGN_LEFT;
999 : : //choose most left positions
1000 [ # # ]: 0 : ::std::sort( aPosList.begin(), aPosList.end(), lcl_LessXPos() );
1001 [ # # ]: 0 : m_aAxisProperties.m_fLabelDirectionSign = fDeltaY<0 ? -1 : 1;
1002 : : }
1003 : : else
1004 : : {
1005 : 0 : m_aAxisProperties.m_aLabelAlignment = LABEL_ALIGN_BOTTOM;
1006 : : //choose most bottom positions
1007 [ # # ]: 0 : ::std::sort( aPosList.begin(), aPosList.end(), lcl_GreaterYPos() );
1008 [ # # ]: 0 : m_aAxisProperties.m_fLabelDirectionSign = fDeltaX<0 ? -1 : 1;
1009 : : }
1010 : 0 : ScreenPosAndLogicPos aBestPos( aPosList[0] );
1011 : 0 : fYStart = fYEnd = aBestPos.fLogicY;
1012 : 0 : fZStart = fZEnd = aBestPos.fLogicZ;
1013 [ # # ][ # # ]: 0 : if( !m_pPosHelper->isMathematicalOrientationX() )
1014 : 0 : m_aAxisProperties.m_fLabelDirectionSign *= -1;
1015 : : }
1016 : : }//end 3D x axis
1017 : : }
1018 [ + + ]: 10378 : else if( 1==m_nDimensionIndex ) //y-axis
1019 : : {
1020 [ + + ]: 10231 : if( fCrossesOtherAxis < fMinX )
1021 : 8616 : fCrossesOtherAxis = fMinX;
1022 [ - + ]: 1615 : else if( fCrossesOtherAxis > fMaxX )
1023 : 0 : fCrossesOtherAxis = fMaxX;
1024 : :
1025 : 10231 : fXStart = fXEnd = fCrossesOtherAxis;
1026 : 10231 : fYEnd=m_pPosHelper->getLogicMaxY();
1027 : :
1028 [ + + ]: 10231 : if(3==m_nDimension)
1029 : : {
1030 [ + - ]: 189 : if( AxisHelper::isAxisPositioningEnabled() )
1031 : : {
1032 [ - + ]: 189 : if( ::rtl::math::approxEqual( fXOther, fXStart) )
1033 : 0 : fZStart = fZEnd = fZOnZPlane;
1034 : : else
1035 : 189 : fZStart = fZEnd = fZOther;
1036 : : }
1037 : : else
1038 : : {
1039 [ # # ][ # # ]: 0 : rStart = getScreenPosition( fXStart, fYStart, fZStart );
1040 [ # # ][ # # ]: 0 : rEnd = getScreenPosition( fXEnd, fYEnd, fZEnd );
1041 : :
1042 : 0 : double fDeltaX = rEnd.getX() - rStart.getX();
1043 : 0 : double fDeltaY = rEnd.getY() - rStart.getY();
1044 : :
1045 : : //only those points are candidates which are lying on exactly one wall as these are outer edges
1046 [ # # ]: 0 : tScreenPosAndLogicPosList aPosList;
1047 [ # # ][ # # ]: 0 : aPosList.push_back( getScreenPosAndLogicPos( fXOnXPlane, fMinY, fZOther ) );
1048 [ # # ][ # # ]: 0 : aPosList.push_back( getScreenPosAndLogicPos( fXOther, fMinY, fZOnZPlane ) );
1049 : :
1050 [ # # ]: 0 : if( fabs(fDeltaY) > fabs(fDeltaX) )
1051 : : {
1052 : 0 : m_aAxisProperties.m_aLabelAlignment = LABEL_ALIGN_LEFT;
1053 : : //choose most left positions
1054 [ # # ]: 0 : ::std::sort( aPosList.begin(), aPosList.end(), lcl_LessXPos() );
1055 [ # # ]: 0 : m_aAxisProperties.m_fLabelDirectionSign = fDeltaY<0 ? -1 : 1;
1056 : : }
1057 : : else
1058 : : {
1059 : 0 : m_aAxisProperties.m_aLabelAlignment = LABEL_ALIGN_BOTTOM;
1060 : : //choose most bottom positions
1061 [ # # ]: 0 : ::std::sort( aPosList.begin(), aPosList.end(), lcl_GreaterYPos() );
1062 [ # # ]: 0 : m_aAxisProperties.m_fLabelDirectionSign = fDeltaX<0 ? -1 : 1;
1063 : : }
1064 : 0 : ScreenPosAndLogicPos aBestPos( aPosList[0] );
1065 : 0 : fXStart = fXEnd = aBestPos.fLogicX;
1066 : 0 : fZStart = fZEnd = aBestPos.fLogicZ;
1067 [ # # ][ # # ]: 0 : if( !m_pPosHelper->isMathematicalOrientationY() )
1068 : 0 : m_aAxisProperties.m_fLabelDirectionSign *= -1;
1069 : : }
1070 : : }//end 3D y axis
1071 : : }
1072 : : else //z-axis
1073 : : {
1074 : 147 : fZEnd = m_pPosHelper->getLogicMaxZ();
1075 [ + - ]: 147 : if( AxisHelper::isAxisPositioningEnabled() )
1076 : : {
1077 [ + + ]: 147 : if( !m_aAxisProperties.m_bSwapXAndY )
1078 : : {
1079 [ - + ]: 109 : if( fCrossesOtherAxis < fMinY )
1080 : 0 : fCrossesOtherAxis = fMinY;
1081 [ - + ]: 109 : else if( fCrossesOtherAxis > fMaxY )
1082 : 0 : fCrossesOtherAxis = fMaxY;
1083 : 109 : fYStart = fYEnd = fCrossesOtherAxis;
1084 : :
1085 [ - + ]: 109 : if( ::rtl::math::approxEqual( fYOther, fYStart) )
1086 : 0 : fXStart = fXEnd = fXOnXPlane;
1087 : : else
1088 : 109 : fXStart = fXEnd = fXOther;
1089 : : }
1090 : : else
1091 : : {
1092 [ + - ]: 38 : if( fCrossesOtherAxis < fMinX )
1093 : 38 : fCrossesOtherAxis = fMinX;
1094 [ # # ]: 0 : else if( fCrossesOtherAxis > fMaxX )
1095 : 0 : fCrossesOtherAxis = fMaxX;
1096 : 38 : fXStart = fXEnd = fCrossesOtherAxis;
1097 : :
1098 [ - + ]: 38 : if( ::rtl::math::approxEqual( fXOther, fXStart) )
1099 : 0 : fYStart = fYEnd = fYOnYPlane;
1100 : : else
1101 : 38 : fYStart = fYEnd = fYOther;
1102 : : }
1103 : : }
1104 : : else
1105 : : {
1106 [ # # ]: 0 : if( !m_pPosHelper->isSwapXAndY() )
1107 : : {
1108 [ # # ]: 0 : fXStart = fXEnd = m_pPosHelper->isMathematicalOrientationX() ? m_pPosHelper->getLogicMaxX() : m_pPosHelper->getLogicMinX();
1109 [ # # ]: 0 : fYStart = fYEnd = m_pPosHelper->isMathematicalOrientationY() ? m_pPosHelper->getLogicMinY() : m_pPosHelper->getLogicMaxY();
1110 : : }
1111 : : else
1112 : : {
1113 [ # # ]: 0 : fXStart = fXEnd = m_pPosHelper->isMathematicalOrientationX() ? m_pPosHelper->getLogicMinX() : m_pPosHelper->getLogicMaxX();
1114 [ # # ]: 0 : fYStart = fYEnd = m_pPosHelper->isMathematicalOrientationY() ? m_pPosHelper->getLogicMaxY() : m_pPosHelper->getLogicMinY();
1115 : : }
1116 : :
1117 [ # # ]: 0 : if(3==m_nDimension)
1118 : : {
1119 [ # # ][ # # ]: 0 : rStart = getScreenPosition( fXStart, fYStart, fZStart );
1120 [ # # ][ # # ]: 0 : rEnd = getScreenPosition( fXEnd, fYEnd, fZEnd );
1121 : :
1122 : 0 : double fDeltaX = rEnd.getX() - rStart.getX();
1123 : :
1124 : : //only those points are candidates which are lying on exactly one wall as these are outer edges
1125 [ # # ]: 0 : tScreenPosAndLogicPosList aPosList;
1126 [ # # ][ # # ]: 0 : aPosList.push_back( getScreenPosAndLogicPos( fXOther, fYOnYPlane, fMinZ ) );
1127 [ # # ][ # # ]: 0 : aPosList.push_back( getScreenPosAndLogicPos( fXOnXPlane, fYOther, fMinZ ) );
1128 : :
1129 [ # # ]: 0 : ::std::sort( aPosList.begin(), aPosList.end(), lcl_GreaterYPos() );
1130 : 0 : ScreenPosAndLogicPos aBestPos( aPosList[0] );
1131 : 0 : ScreenPosAndLogicPos aNotSoGoodPos( aPosList[1] );
1132 : :
1133 : : //choose most bottom positions
1134 [ # # ]: 0 : if( !::rtl::math::approxEqual( fDeltaX, 0.0 ) ) // prefere left-right algnments
1135 : : {
1136 [ # # ]: 0 : if( aBestPos.aScreenPos.getX() > aNotSoGoodPos.aScreenPos.getX() )
1137 : 0 : m_aAxisProperties.m_aLabelAlignment = LABEL_ALIGN_RIGHT;
1138 : : else
1139 : 0 : m_aAxisProperties.m_aLabelAlignment = LABEL_ALIGN_LEFT;
1140 : : }
1141 : : else
1142 : : {
1143 [ # # ]: 0 : if( aBestPos.aScreenPos.getY() > aNotSoGoodPos.aScreenPos.getY() )
1144 : 0 : m_aAxisProperties.m_aLabelAlignment = LABEL_ALIGN_BOTTOM;
1145 : : else
1146 : 0 : m_aAxisProperties.m_aLabelAlignment = LABEL_ALIGN_TOP;
1147 : : }
1148 : :
1149 [ # # ]: 0 : m_aAxisProperties.m_fLabelDirectionSign = fDeltaX<0 ? -1 : 1;
1150 [ # # ][ # # ]: 0 : if( !m_pPosHelper->isMathematicalOrientationZ() )
1151 : 0 : m_aAxisProperties.m_fLabelDirectionSign *= -1;
1152 : :
1153 : 0 : fXStart = fXEnd = aBestPos.fLogicX;
1154 : 0 : fYStart = fYEnd = aBestPos.fLogicY;
1155 : : }
1156 : : }//end 3D z axis
1157 : : }
1158 : :
1159 [ + - ]: 22882 : rStart = getScreenPosition( fXStart, fYStart, fZStart );
1160 [ + - ]: 22882 : rEnd = getScreenPosition( fXEnd, fYEnd, fZEnd );
1161 : :
1162 [ - + ][ - + ]: 22882 : if(3==m_nDimension && !AxisHelper::isAxisPositioningEnabled() )
[ + + ]
1163 : 0 : m_aAxisProperties.m_fInnerDirectionSign = m_aAxisProperties.m_fLabelDirectionSign;//to behave like before
1164 : :
1165 [ + + ][ + - ]: 22882 : if(3==m_nDimension && AxisHelper::isAxisPositioningEnabled() )
[ + + ]
1166 : : {
1167 : 518 : double fDeltaX = rEnd.getX() - rStart.getX();
1168 : 518 : double fDeltaY = rEnd.getY() - rStart.getY();
1169 : :
1170 [ + + ]: 518 : if( 2==m_nDimensionIndex )
1171 : : {
1172 [ - + ]: 147 : if( m_eLeftWallPos != CuboidPlanePosition_Left )
1173 : : {
1174 : 0 : m_aAxisProperties.m_fLabelDirectionSign *= -1.0;
1175 : 0 : m_aAxisProperties.m_fInnerDirectionSign *= -1.0;
1176 : : }
1177 : :
1178 : : m_aAxisProperties.m_aLabelAlignment =
1179 : : ( m_aAxisProperties.m_fLabelDirectionSign<0 ) ?
1180 [ - + ]: 147 : LABEL_ALIGN_LEFT : LABEL_ALIGN_RIGHT;
1181 : :
1182 [ + - ][ + - ]: 147 : if( ( fDeltaY<0 && m_aScale.Orientation == AxisOrientation_REVERSE ) ||
[ - + ][ # # ]
1183 : : ( fDeltaY>0 && m_aScale.Orientation == AxisOrientation_MATHEMATICAL ) )
1184 : : m_aAxisProperties.m_aLabelAlignment =
1185 : : ( m_aAxisProperties.m_aLabelAlignment==LABEL_ALIGN_RIGHT ) ?
1186 [ # # ]: 0 : LABEL_ALIGN_LEFT : LABEL_ALIGN_RIGHT;
1187 : : }
1188 [ + + ]: 371 : else if( fabs(fDeltaY) > fabs(fDeltaX) )
1189 : : {
1190 [ - + ]: 189 : if( m_eBackWallPos != CuboidPlanePosition_Back )
1191 : : {
1192 : 0 : m_aAxisProperties.m_fLabelDirectionSign *= -1.0;
1193 : 0 : m_aAxisProperties.m_fInnerDirectionSign *= -1.0;
1194 : : }
1195 : :
1196 : : m_aAxisProperties.m_aLabelAlignment =
1197 : : ( m_aAxisProperties.m_fLabelDirectionSign<0 ) ?
1198 [ + - ]: 189 : LABEL_ALIGN_LEFT : LABEL_ALIGN_RIGHT;
1199 : :
1200 [ + - ][ + - ]: 189 : if( ( fDeltaY<0 && m_aScale.Orientation == AxisOrientation_REVERSE ) ||
[ - + ][ # # ]
1201 : : ( fDeltaY>0 && m_aScale.Orientation == AxisOrientation_MATHEMATICAL ) )
1202 : : m_aAxisProperties.m_aLabelAlignment =
1203 : : ( m_aAxisProperties.m_aLabelAlignment==LABEL_ALIGN_RIGHT ) ?
1204 [ # # ]: 0 : LABEL_ALIGN_LEFT : LABEL_ALIGN_RIGHT;
1205 : : }
1206 : : else
1207 : : {
1208 [ - + ]: 182 : if( m_eBackWallPos != CuboidPlanePosition_Back )
1209 : : {
1210 : 0 : m_aAxisProperties.m_fLabelDirectionSign *= -1.0;
1211 : 0 : m_aAxisProperties.m_fInnerDirectionSign *= -1.0;
1212 : : }
1213 : :
1214 : : m_aAxisProperties.m_aLabelAlignment =
1215 : : ( m_aAxisProperties.m_fLabelDirectionSign<0 ) ?
1216 [ - + ]: 182 : LABEL_ALIGN_TOP : LABEL_ALIGN_BOTTOM;
1217 : :
1218 [ + - ][ + - ]: 182 : if( ( fDeltaX>0 && m_aScale.Orientation == AxisOrientation_REVERSE ) ||
[ - + ][ # # ]
1219 : : ( fDeltaX<0 && m_aScale.Orientation == AxisOrientation_MATHEMATICAL ) )
1220 : : m_aAxisProperties.m_aLabelAlignment =
1221 : : ( m_aAxisProperties.m_aLabelAlignment==LABEL_ALIGN_TOP ) ?
1222 [ # # ]: 0 : LABEL_ALIGN_BOTTOM : LABEL_ALIGN_TOP;
1223 : : }
1224 : : }
1225 : 22882 : }
1226 : :
1227 : 3640 : TickFactory* VCartesianAxis::createTickFactory()
1228 : : {
1229 : 3640 : return createTickFactory2D();
1230 : : }
1231 : :
1232 : 10598 : TickFactory_2D* VCartesianAxis::createTickFactory2D()
1233 : : {
1234 : 10598 : B2DVector aStart, aEnd;
1235 [ + - ][ + - ]: 10598 : this->get2DAxisMainLine( aStart, aEnd, this->getLogicValueWhereMainLineCrossesOtherAxis() );
1236 : :
1237 : 10598 : B2DVector aLabelLineStart, aLabelLineEnd;
1238 [ + - ][ + - ]: 10598 : this->get2DAxisMainLine( aLabelLineStart, aLabelLineEnd, this->getLogicValueWhereLabelLineCrossesOtherAxis() );
1239 : :
1240 [ + - ][ + - ]: 10598 : return new TickFactory_2D( m_aScale, m_aIncrement, aStart, aEnd, aLabelLineStart-aStart );
1241 : : }
1242 : :
1243 : 2568 : void lcl_hideIdenticalScreenValues( TickIter& rTickIter )
1244 : : {
1245 : 2568 : TickInfo* pPreviousTickInfo = rTickIter.firstInfo();
1246 [ - + ]: 2568 : if(!pPreviousTickInfo)
1247 : 2568 : return;
1248 : 2568 : pPreviousTickInfo->bPaintIt = true;
1249 [ + + ]: 27346 : for( TickInfo* pTickInfo = rTickIter.nextInfo(); pTickInfo; pTickInfo = rTickIter.nextInfo())
1250 : : {
1251 : : pTickInfo->bPaintIt =
1252 : 24778 : ( static_cast<sal_Int32>(pTickInfo->aTickScreenPosition.getX())
1253 : 24778 : != static_cast<sal_Int32>(pPreviousTickInfo->aTickScreenPosition.getX()) )
1254 : : ||
1255 : 9092 : ( static_cast<sal_Int32>(pTickInfo->aTickScreenPosition.getY())
1256 [ + + + - ]: 33870 : != static_cast<sal_Int32>(pPreviousTickInfo->aTickScreenPosition.getY()) );
1257 : 24778 : pPreviousTickInfo = pTickInfo;
1258 : : }
1259 : : }
1260 : :
1261 : : //'hide' tickmarks with identical screen values in aAllTickInfos
1262 : 2568 : void VCartesianAxis::hideIdenticalScreenValues( ::std::vector< ::std::vector< TickInfo > >& rTickInfos ) const
1263 : : {
1264 [ + - ][ - + ]: 2568 : if( isComplexCategoryAxis() || isDateAxis() )
[ - + ]
1265 : : {
1266 : 0 : sal_Int32 nCount = rTickInfos.size();
1267 [ # # ]: 0 : for( sal_Int32 nN=0; nN<nCount; nN++ )
1268 : : {
1269 [ # # ]: 0 : PureTickIter aTickIter( rTickInfos[nN] );
1270 [ # # ]: 0 : lcl_hideIdenticalScreenValues( aTickIter );
1271 [ # # ]: 0 : }
1272 : : }
1273 : : else
1274 : : {
1275 [ + - ]: 2568 : EquidistantTickIter aTickIter( rTickInfos, m_aIncrement, 0, -1 );
1276 [ + - ][ + - ]: 2568 : lcl_hideIdenticalScreenValues( aTickIter );
1277 : : }
1278 : 2568 : }
1279 : :
1280 : 3890 : sal_Int32 VCartesianAxis::estimateMaximumAutoMainIncrementCount()
1281 : : {
1282 : 3890 : sal_Int32 nRet = 10;
1283 : :
1284 [ + + ][ + - ]: 3890 : if( m_nMaximumTextWidthSoFar==0 && m_nMaximumTextHeightSoFar==0 )
1285 : 2204 : return nRet;
1286 : :
1287 : 1686 : B2DVector aStart, aEnd;
1288 [ + - ][ + - ]: 1686 : this->get2DAxisMainLine( aStart, aEnd, this->getLogicValueWhereMainLineCrossesOtherAxis() );
1289 : :
1290 : 1686 : sal_Int32 nMaxHeight = static_cast<sal_Int32>(fabs(aEnd.getY()-aStart.getY()));
1291 : 1686 : sal_Int32 nMaxWidth = static_cast<sal_Int32>(fabs(aEnd.getX()-aStart.getX()));
1292 : :
1293 : 1686 : sal_Int32 nTotalAvailable = nMaxHeight;
1294 : 1686 : sal_Int32 nSingleNeeded = m_nMaximumTextHeightSoFar;
1295 : :
1296 : : //for horizontal axis:
1297 [ + + ][ + + ]: 1686 : if( (m_nDimensionIndex == 0 && !m_aAxisProperties.m_bSwapXAndY)
[ + + ][ + + ]
1298 : : || (m_nDimensionIndex == 1 && m_aAxisProperties.m_bSwapXAndY) )
1299 : : {
1300 : 960 : nTotalAvailable = nMaxWidth;
1301 : 960 : nSingleNeeded = m_nMaximumTextWidthSoFar;
1302 : : }
1303 : :
1304 [ + - ]: 1686 : if( nSingleNeeded>0 )
1305 : 1686 : nRet = nTotalAvailable/nSingleNeeded;
1306 : :
1307 : 3890 : return nRet;
1308 : : }
1309 : :
1310 : 5138 : void VCartesianAxis::doStaggeringOfLabels( const AxisLabelProperties& rAxisLabelProperties, TickFactory_2D* pTickFactory2D )
1311 : : {
1312 [ - + ]: 5138 : if( !pTickFactory2D )
1313 : 5138 : return;
1314 : :
1315 [ - + ]: 5138 : if( isComplexCategoryAxis() )
1316 : : {
1317 [ # # ]: 0 : sal_Int32 nTextLevelCount = getTextLevelCount();
1318 : 0 : B2DVector aCummulatedLabelsDistance(0,0);
1319 [ # # ]: 0 : for( sal_Int32 nTextLevel=0; nTextLevel<nTextLevelCount; nTextLevel++ )
1320 : : {
1321 [ # # ]: 0 : boost::scoped_ptr< TickIter > apTickIter(createLabelTickIterator( nTextLevel ));
1322 [ # # ]: 0 : if(apTickIter)
1323 : : {
1324 : 0 : double fRotationAngleDegree = m_aAxisLabelProperties.fRotationAngleDegree;
1325 : 0 : aCummulatedLabelsDistance += lcl_getLabelsDistance( *apTickIter.get()
1326 : : , pTickFactory2D->getDistanceAxisTickToText( m_aAxisProperties )
1327 [ # # # # ]: 0 : , fRotationAngleDegree );
1328 : : }
1329 [ # # ]: 0 : }
1330 : : }
1331 [ + + ]: 5138 : else if( rAxisLabelProperties.getIsStaggered() )
1332 : : {
1333 [ + + ]: 949 : if( !m_aAllTickInfos.empty() )
1334 : : {
1335 [ + - ]: 892 : LabelIterator aInnerIter( m_aAllTickInfos[0], rAxisLabelProperties.eStaggering, true );
1336 [ + - ]: 892 : LabelIterator aOuterIter( m_aAllTickInfos[0], rAxisLabelProperties.eStaggering, false );
1337 : :
1338 : : lcl_shiftLables( aOuterIter
1339 : : , lcl_getLabelsDistance( aInnerIter
1340 [ + - ][ + - ]: 892 : , pTickFactory2D->getDistanceAxisTickToText( m_aAxisProperties ), 0.0 ) );
[ + - ][ + - ]
[ + - ]
1341 : : }
1342 : : }
1343 : : }
1344 : :
1345 : 1938 : void VCartesianAxis::createLabels()
1346 : : {
1347 [ + + ]: 1938 : if( !prepareShapeCreation() )
1348 : 118 : return;
1349 : :
1350 : : //-----------------------------------------
1351 : : //create labels
1352 [ + + ]: 1820 : if( m_aAxisProperties.m_bDisplayLabels )
1353 : : {
1354 [ + - ]: 1681 : boost::scoped_ptr< TickFactory_2D > apTickFactory2D( this->createTickFactory2D() );
1355 : 1681 : TickFactory_2D* pTickFactory2D = apTickFactory2D.get();
1356 [ - + ]: 1681 : if( !pTickFactory2D )
1357 : : return;
1358 : :
1359 : : //-----------------------------------------
1360 : : //get the transformed screen values for all tickmarks in aAllTickInfos
1361 [ + - ]: 1681 : pTickFactory2D->updateScreenValues( m_aAllTickInfos );
1362 : : //-----------------------------------------
1363 : : //'hide' tickmarks with identical screen values in aAllTickInfos
1364 [ + - ]: 1681 : hideIdenticalScreenValues( m_aAllTickInfos );
1365 : :
1366 [ + - ]: 1681 : removeTextShapesFromTicks();
1367 : :
1368 : : //create tick mark text shapes
1369 [ + - ]: 1681 : sal_Int32 nTextLevelCount = getTextLevelCount();
1370 : 1681 : sal_Int32 nScreenDistanceBetweenTicks = -1;
1371 [ + + ]: 3362 : for( sal_Int32 nTextLevel=0; nTextLevel<nTextLevelCount; nTextLevel++ )
1372 : : {
1373 [ + - ]: 1681 : boost::scoped_ptr< TickIter > apTickIter(createLabelTickIterator( nTextLevel ));
1374 [ + - ]: 1681 : if(apTickIter)
1375 : : {
1376 [ + - ]: 1681 : if(nTextLevel==0)
1377 : : {
1378 [ + - ]: 1681 : nScreenDistanceBetweenTicks = TickFactory_2D::getTickScreenDistance( *apTickIter.get() );
1379 [ - + ]: 1681 : if( nTextLevelCount>1 )
1380 : 0 : nScreenDistanceBetweenTicks*=2; //the above used tick iter does contain also the sub ticks -> thus the given distance is only the half
1381 : : }
1382 : :
1383 : 1681 : AxisLabelProperties aComplexProps(m_aAxisLabelProperties);
1384 [ - + ]: 1681 : if( m_aAxisProperties.m_bComplexCategories )
1385 : : {
1386 : 0 : aComplexProps.bLineBreakAllowed = true;
1387 : 0 : aComplexProps.bOverlapAllowed = !::rtl::math::approxEqual( aComplexProps.fRotationAngleDegree, 0.0 );
1388 : :
1389 : : }
1390 [ - + ]: 1681 : AxisLabelProperties& rAxisLabelProperties = m_aAxisProperties.m_bComplexCategories ? aComplexProps : m_aAxisLabelProperties;
1391 [ + - ][ + + ]: 1739 : while( !createTextShapes( m_xTextTarget, *apTickIter.get(), rAxisLabelProperties, pTickFactory2D, nScreenDistanceBetweenTicks ) )
1392 : : {
1393 : : };
1394 : : }
1395 [ + - ]: 1681 : }
1396 [ + - ][ + - ]: 1938 : doStaggeringOfLabels( m_aAxisLabelProperties, pTickFactory2D );
[ + - ]
1397 : : }
1398 : : }
1399 : :
1400 : 1938 : void VCartesianAxis::createMaximumLabels()
1401 : : {
1402 [ + - ]: 1938 : TrueGuard aRecordMaximumTextSize(m_bRecordMaximumTextSize);
1403 : :
1404 [ + - ][ + + ]: 1938 : if( !prepareShapeCreation() )
1405 : : return;
1406 : :
1407 : : //-----------------------------------------
1408 : : //create labels
1409 [ + + ]: 1820 : if( m_aAxisProperties.m_bDisplayLabels )
1410 : : {
1411 [ + - ]: 1681 : boost::scoped_ptr< TickFactory_2D > apTickFactory2D( this->createTickFactory2D() );
1412 : 1681 : TickFactory_2D* pTickFactory2D = apTickFactory2D.get();
1413 [ - + ]: 1681 : if( !pTickFactory2D )
1414 : : return;
1415 : :
1416 : : //-----------------------------------------
1417 : : //get the transformed screen values for all tickmarks in aAllTickInfos
1418 [ + - ]: 1681 : pTickFactory2D->updateScreenValues( m_aAllTickInfos );
1419 : :
1420 : : //create tick mark text shapes
1421 : : //@todo: iterate through all tick depth wich should be labeled
1422 : :
1423 : 1681 : AxisLabelProperties aAxisLabelProperties( m_aAxisLabelProperties );
1424 [ + - ][ + - ]: 1681 : if( isAutoStaggeringOfLabelsAllowed( aAxisLabelProperties, pTickFactory2D->isHorizontalAxis(), pTickFactory2D->isVerticalAxis() ) )
[ + + ]
1425 : 856 : aAxisLabelProperties.eStaggering = STAGGER_EVEN;
1426 : 1681 : aAxisLabelProperties.bOverlapAllowed = true;
1427 : 1681 : aAxisLabelProperties.bLineBreakAllowed = false;
1428 [ + - ]: 1681 : sal_Int32 nTextLevelCount = getTextLevelCount();
1429 [ + + ]: 3362 : for( sal_Int32 nTextLevel=0; nTextLevel<nTextLevelCount; nTextLevel++ )
1430 : : {
1431 [ + - ]: 1681 : boost::scoped_ptr< TickIter > apTickIter(createMaximumLabelTickIterator( nTextLevel ));
1432 [ + - ]: 1681 : if(apTickIter)
1433 : : {
1434 [ + - ][ - + ]: 1681 : while( !createTextShapes( m_xTextTarget, *apTickIter.get(), aAxisLabelProperties, pTickFactory2D, -1 ) )
1435 : : {
1436 : : };
1437 : : }
1438 [ + - ]: 1681 : }
1439 [ + - ][ + - ]: 1820 : doStaggeringOfLabels( aAxisLabelProperties, pTickFactory2D );
[ + - ]
1440 [ + - ][ + + ]: 1938 : }
1441 : : }
1442 : :
1443 : 1938 : void VCartesianAxis::updatePositions()
1444 : : {
1445 : : //-----------------------------------------
1446 : : //update positions of labels
1447 [ + + ]: 1938 : if( m_aAxisProperties.m_bDisplayLabels )
1448 : : {
1449 [ + - ]: 1776 : boost::scoped_ptr< TickFactory_2D > apTickFactory2D( this->createTickFactory2D() );
1450 : 1776 : TickFactory_2D* pTickFactory2D = apTickFactory2D.get();
1451 [ - + ]: 1776 : if( !pTickFactory2D )
1452 : 1938 : return;
1453 : :
1454 : : //-----------------------------------------
1455 : : //update positions of all existing text shapes
1456 [ + - ]: 1776 : pTickFactory2D->updateScreenValues( m_aAllTickInfos );
1457 : :
1458 : 1776 : ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter = m_aAllTickInfos.begin();
1459 [ + - ]: 1776 : const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd = m_aAllTickInfos.end();
1460 [ + - ][ + + ]: 5138 : for( sal_Int32 nDepth=0; aDepthIter != aDepthEnd; ++aDepthIter, nDepth++ )
1461 : : {
1462 : 3362 : ::std::vector< TickInfo >::iterator aTickIter = aDepthIter->begin();
1463 [ + - ]: 3362 : const ::std::vector< TickInfo >::const_iterator aTickEnd = aDepthIter->end();
1464 [ + - ][ + + ]: 22759 : for( ; aTickIter != aTickEnd; ++aTickIter )
1465 : : {
1466 : 19397 : TickInfo& rTickInfo = (*aTickIter);
1467 : 19397 : Reference< drawing::XShape > xShape2DText( rTickInfo.xTextShape );
1468 [ + + ]: 19397 : if( xShape2DText.is() )
1469 : : {
1470 [ + - ]: 9258 : B2DVector aTextToTickDistance( pTickFactory2D->getDistanceAxisTickToText( m_aAxisProperties, true ) );
1471 : 9258 : B2DVector aTickScreenPos2D( rTickInfo.aTickScreenPosition );
1472 : 9258 : aTickScreenPos2D += aTextToTickDistance;
1473 : : awt::Point aAnchorScreenPosition2D(
1474 : 9258 : static_cast<sal_Int32>(aTickScreenPos2D.getX())
1475 : 18516 : ,static_cast<sal_Int32>(aTickScreenPos2D.getY()));
1476 : :
1477 : 9258 : double fRotationAngleDegree = m_aAxisLabelProperties.fRotationAngleDegree;
1478 : :
1479 : : // #i78696# use mathematically correct rotation now
1480 : 9258 : const double fRotationAnglePi(fRotationAngleDegree * (F_PI / -180.0));
1481 [ + - ]: 9258 : uno::Any aATransformation = ShapeFactory::makeTransformation(aAnchorScreenPosition2D, fRotationAnglePi);
1482 : :
1483 : : //set new position
1484 [ + - ]: 9258 : uno::Reference< beans::XPropertySet > xProp( xShape2DText, uno::UNO_QUERY );
1485 [ + - ]: 9258 : if( xProp.is() )
1486 : : {
1487 : : try
1488 : : {
1489 [ + - ][ + - ]: 9258 : xProp->setPropertyValue( C2U( "Transformation" ), aATransformation );
[ + - ][ # # ]
1490 : : }
1491 [ # # ]: 0 : catch( const uno::Exception& e )
1492 : : {
1493 : : ASSERT_EXCEPTION( e );
1494 : : }
1495 : : }
1496 : :
1497 : : //correctPositionForRotation
1498 : : LabelPositionHelper::correctPositionForRotation( xShape2DText
1499 [ + - ]: 9258 : , m_aAxisProperties.m_aLabelAlignment, fRotationAngleDegree, m_aAxisProperties.m_bComplexCategories );
1500 : : }
1501 : 19397 : }
1502 : : }
1503 : :
1504 [ + - ][ + - ]: 1776 : doStaggeringOfLabels( m_aAxisLabelProperties, pTickFactory2D );
[ + - ]
1505 : : }
1506 : : }
1507 : :
1508 : 1928 : void VCartesianAxis::createTickMarkLineShapes( ::std::vector< TickInfo >& rTickInfos, const TickmarkProperties& rTickmarkProperties, TickFactory_2D& rTickFactory2D, bool bOnlyAtLabels )
1509 : : {
1510 : 1928 : sal_Int32 nPointCount = rTickInfos.size();
1511 [ + - ]: 1928 : drawing::PointSequenceSequence aPoints(2*nPointCount);
1512 : :
1513 [ + - ]: 1928 : ::std::vector< TickInfo >::const_iterator aTickIter = rTickInfos.begin();
1514 [ + - ]: 1928 : const ::std::vector< TickInfo >::const_iterator aTickEnd = rTickInfos.end();
1515 : 1928 : sal_Int32 nN = 0;
1516 [ + - ][ + + ]: 13867 : for( ; aTickIter != aTickEnd; ++aTickIter )
1517 : : {
1518 [ - + ]: 11939 : if( !(*aTickIter).bPaintIt )
1519 : 0 : continue;
1520 : :
1521 : 11939 : bool bTicksAtLabels = ( m_aAxisProperties.m_eTickmarkPos != ::com::sun::star::chart::ChartAxisMarkPosition_AT_AXIS );
1522 : 11939 : double fInnerDirectionSign = m_aAxisProperties.m_fInnerDirectionSign;
1523 [ + + ][ - + ]: 11939 : if( bTicksAtLabels && m_aAxisProperties.m_eLabelPos == ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_END )
1524 : 0 : fInnerDirectionSign *= -1.0;
1525 [ + + ][ - + ]: 11939 : bTicksAtLabels = bTicksAtLabels || bOnlyAtLabels;
1526 : : //add ticks at labels:
1527 : 11939 : rTickFactory2D.addPointSequenceForTickLine( aPoints, nN++, (*aTickIter).fScaledTickValue
1528 [ + - ]: 11939 : , fInnerDirectionSign , rTickmarkProperties, bTicksAtLabels );
1529 : : //add ticks at axis (without lables):
1530 [ + - ][ + + ]: 11939 : if( !bOnlyAtLabels && m_aAxisProperties.m_eTickmarkPos == ::com::sun::star::chart::ChartAxisMarkPosition_AT_LABELS_AND_AXIS )
1531 : 10265 : rTickFactory2D.addPointSequenceForTickLine( aPoints, nN++, (*aTickIter).fScaledTickValue
1532 [ + - ]: 10265 : , m_aAxisProperties.m_fInnerDirectionSign, rTickmarkProperties, !bTicksAtLabels );
1533 : : }
1534 [ + - ]: 1928 : aPoints.realloc(nN);
1535 : : m_pShapeFactory->createLine2D( m_xGroupShape_Shapes, aPoints
1536 [ + - ][ + - ]: 1928 : , &rTickmarkProperties.aLineProperties );
1537 : 1928 : }
1538 : :
1539 : 1938 : void VCartesianAxis::createShapes()
1540 : : {
1541 [ + - ][ + + ]: 1938 : if( !prepareShapeCreation() )
1542 : : return;
1543 : :
1544 [ + - ]: 1820 : boost::scoped_ptr< TickFactory_2D > apTickFactory2D( this->createTickFactory2D() );
1545 : 1820 : TickFactory_2D* pTickFactory2D = apTickFactory2D.get();
1546 [ - + ]: 1820 : if( !pTickFactory2D )
1547 : : return;
1548 : :
1549 : : //-----------------------------------------
1550 : : //create line shapes
1551 [ + + ]: 1820 : if(2==m_nDimension)
1552 : : {
1553 : : //-----------------------------------------
1554 : : //create extra long ticks to separate complex categories (create them only there where the labels are)
1555 [ + - ][ - + ]: 1778 : if( isComplexCategoryAxis() )
1556 : : {
1557 [ # # ]: 0 : ::std::vector< ::std::vector< TickInfo > > aComplexTickInfos;
1558 [ # # ]: 0 : createAllTickInfosFromComplexCategories( aComplexTickInfos, true );
1559 [ # # ]: 0 : pTickFactory2D->updateScreenValues( aComplexTickInfos );
1560 [ # # ]: 0 : hideIdenticalScreenValues( aComplexTickInfos );
1561 : :
1562 [ # # ]: 0 : ::std::vector<TickmarkProperties> aTickmarkPropertiesList;
1563 : : static bool bIncludeSpaceBetweenTickAndText = false;
1564 [ # # ][ # # ]: 0 : sal_Int32 nOffset = static_cast<sal_Int32>(pTickFactory2D->getDistanceAxisTickToText( m_aAxisProperties, false, bIncludeSpaceBetweenTickAndText ).getLength());
1565 [ # # ]: 0 : sal_Int32 nTextLevelCount = getTextLevelCount();
1566 [ # # ]: 0 : for( sal_Int32 nTextLevel=0; nTextLevel<nTextLevelCount; nTextLevel++ )
1567 : : {
1568 [ # # ]: 0 : boost::scoped_ptr< TickIter > apTickIter(createLabelTickIterator( nTextLevel ));
1569 [ # # ]: 0 : if( apTickIter )
1570 : : {
1571 : 0 : double fRotationAngleDegree = m_aAxisLabelProperties.fRotationAngleDegree;
1572 [ # # ][ # # ]: 0 : B2DVector aLabelsDistance( lcl_getLabelsDistance( *apTickIter.get(), pTickFactory2D->getDistanceAxisTickToText( m_aAxisProperties, false ), fRotationAngleDegree ) );
1573 [ # # ]: 0 : sal_Int32 nCurrentLength = static_cast<sal_Int32>(aLabelsDistance.getLength());
1574 [ # # ][ # # ]: 0 : aTickmarkPropertiesList.push_back( m_aAxisProperties.makeTickmarkPropertiesForComplexCategories( nOffset + nCurrentLength, 0, nTextLevel ) );
1575 : 0 : nOffset += nCurrentLength;
1576 : : }
1577 [ # # ]: 0 : }
1578 : :
1579 : 0 : sal_Int32 nTickmarkPropertiesCount = aTickmarkPropertiesList.size();
1580 : 0 : ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter = aComplexTickInfos.begin();
1581 [ # # ]: 0 : const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd = aComplexTickInfos.end();
1582 [ # # ][ # # ]: 0 : for( sal_Int32 nDepth=0; aDepthIter != aDepthEnd && nDepth < nTickmarkPropertiesCount; ++aDepthIter, nDepth++ )
[ # # ][ # # ]
1583 : : {
1584 [ # # ][ # # ]: 0 : if(nDepth==0 && !m_aAxisProperties.m_nMajorTickmarks)
1585 : 0 : continue;
1586 [ # # ]: 0 : createTickMarkLineShapes( *aDepthIter, aTickmarkPropertiesList[nDepth], *pTickFactory2D, true /*bOnlyAtLabels*/ );
1587 : 0 : }
1588 : : }
1589 : : //-----------------------------------------
1590 : : //create normal ticks for major and minor intervals
1591 : : {
1592 [ + - ]: 1778 : ::std::vector< ::std::vector< TickInfo > > aUnshiftedTickInfos;
1593 [ + + ]: 1778 : if( m_aScale.ShiftedCategoryPosition )// if ShiftedCategoryPosition==true the tickmarks in m_aAllTickInfos are shifted
1594 : : {
1595 [ + - ]: 887 : pTickFactory2D->getAllTicks( aUnshiftedTickInfos );
1596 [ + - ]: 887 : pTickFactory2D->updateScreenValues( aUnshiftedTickInfos );
1597 [ + - ]: 887 : hideIdenticalScreenValues( aUnshiftedTickInfos );
1598 : : }
1599 [ + + ]: 1778 : ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos = m_aScale.ShiftedCategoryPosition ? aUnshiftedTickInfos : m_aAllTickInfos;
1600 : :
1601 : 1778 : ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter = rAllTickInfos.begin();
1602 [ + - ]: 1778 : const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd = rAllTickInfos.end();
1603 [ + - ][ - + ]: 1778 : if(aDepthIter == aDepthEnd)//no tickmarks at all
1604 : : return;
1605 : :
1606 : 1778 : sal_Int32 nTickmarkPropertiesCount = m_aAxisProperties.m_aTickmarkPropertiesList.size();
1607 [ + - ][ + + ]: 3706 : for( sal_Int32 nDepth=0; aDepthIter != aDepthEnd && nDepth < nTickmarkPropertiesCount; ++aDepthIter, nDepth++ )
[ + + ][ + + ]
1608 [ + - ][ + - ]: 3706 : createTickMarkLineShapes( *aDepthIter, m_aAxisProperties.m_aTickmarkPropertiesList[nDepth], *pTickFactory2D, false /*bOnlyAtLabels*/ );
1609 : : }
1610 : : //-----------------------------------------
1611 : : //create axis main lines
1612 : : //it serves also as the handle shape for the axis selection
1613 : : {
1614 [ + - ]: 1778 : drawing::PointSequenceSequence aPoints(1);
1615 [ + - ]: 1778 : apTickFactory2D->createPointSequenceForAxisMainLine( aPoints );
1616 : : Reference< drawing::XShape > xShape = m_pShapeFactory->createLine2D(
1617 : : m_xGroupShape_Shapes, aPoints
1618 [ + - ]: 1778 : , &m_aAxisProperties.m_aLineProperties );
1619 : : //because of this name this line will be used for marking the axis
1620 [ + - ][ + - ]: 1778 : m_pShapeFactory->setShapeName( xShape, C2U("MarkHandles") );
[ + - ]
1621 : : }
1622 : : //-----------------------------------------
1623 : : //create an additional line at NULL
1624 [ + - ][ - + ]: 1778 : if( !AxisHelper::isAxisPositioningEnabled() )
1625 : : {
1626 : : double fExtraLineCrossesOtherAxis;
1627 [ # # ][ # # ]: 0 : if( getLogicValueWhereExtraLineCrossesOtherAxis(fExtraLineCrossesOtherAxis) )
1628 : : {
1629 : 0 : B2DVector aStart, aEnd;
1630 [ # # ]: 0 : this->get2DAxisMainLine( aStart, aEnd, fExtraLineCrossesOtherAxis );
1631 [ # # ]: 0 : drawing::PointSequenceSequence aPoints( lcl_makePointSequence(aStart,aEnd) );
1632 : : Reference< drawing::XShape > xShape = m_pShapeFactory->createLine2D(
1633 [ # # ][ # # ]: 1820 : m_xGroupShape_Shapes, aPoints, &m_aAxisProperties.m_aLineProperties );
1634 : : }
1635 : : }
1636 [ + - ][ + - ]: 1938 : }
1637 : :
1638 : : //createLabels();
1639 : : }
1640 : :
1641 : : //.............................................................................
1642 : : } //namespace chart
1643 : : //.............................................................................
1644 : :
1645 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|