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