1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_chart2.hxx"
30*cdf0e10cSrcweir #include <basegfx/numeric/ftools.hxx>
31*cdf0e10cSrcweir 
32*cdf0e10cSrcweir #include "VPolarAngleAxis.hxx"
33*cdf0e10cSrcweir #include "VPolarGrid.hxx"
34*cdf0e10cSrcweir #include "ShapeFactory.hxx"
35*cdf0e10cSrcweir #include "macros.hxx"
36*cdf0e10cSrcweir #include "NumberFormatterWrapper.hxx"
37*cdf0e10cSrcweir #include "PolarLabelPositionHelper.hxx"
38*cdf0e10cSrcweir #include <tools/color.hxx>
39*cdf0e10cSrcweir 
40*cdf0e10cSrcweir #include <memory>
41*cdf0e10cSrcweir 
42*cdf0e10cSrcweir //.............................................................................
43*cdf0e10cSrcweir namespace chart
44*cdf0e10cSrcweir {
45*cdf0e10cSrcweir //.............................................................................
46*cdf0e10cSrcweir using namespace ::com::sun::star;
47*cdf0e10cSrcweir using namespace ::com::sun::star::chart2;
48*cdf0e10cSrcweir using namespace ::rtl::math;
49*cdf0e10cSrcweir 
50*cdf0e10cSrcweir VPolarAngleAxis::VPolarAngleAxis( const AxisProperties& rAxisProperties
51*cdf0e10cSrcweir             , const uno::Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier
52*cdf0e10cSrcweir             , sal_Int32 nDimensionCount )
53*cdf0e10cSrcweir             : VPolarAxis( rAxisProperties, xNumberFormatsSupplier, 0/*nDimensionIndex*/, nDimensionCount )
54*cdf0e10cSrcweir {
55*cdf0e10cSrcweir }
56*cdf0e10cSrcweir 
57*cdf0e10cSrcweir VPolarAngleAxis::~VPolarAngleAxis()
58*cdf0e10cSrcweir {
59*cdf0e10cSrcweir     delete m_pPosHelper;
60*cdf0e10cSrcweir     m_pPosHelper = NULL;
61*cdf0e10cSrcweir }
62*cdf0e10cSrcweir 
63*cdf0e10cSrcweir bool VPolarAngleAxis::createTextShapes_ForAngleAxis(
64*cdf0e10cSrcweir                        const uno::Reference< drawing::XShapes >& xTarget
65*cdf0e10cSrcweir                      , EquidistantTickIter& rTickIter
66*cdf0e10cSrcweir                      , AxisLabelProperties& rAxisLabelProperties
67*cdf0e10cSrcweir                      , double fLogicRadius
68*cdf0e10cSrcweir                      , double fLogicZ )
69*cdf0e10cSrcweir {
70*cdf0e10cSrcweir     sal_Int32 nDimensionCount = 2;
71*cdf0e10cSrcweir     ShapeFactory aShapeFactory(m_xShapeFactory);
72*cdf0e10cSrcweir 
73*cdf0e10cSrcweir     FixedNumberFormatter aFixedNumberFormatter(
74*cdf0e10cSrcweir         m_xNumberFormatsSupplier, rAxisLabelProperties.nNumberFormatKey );
75*cdf0e10cSrcweir 
76*cdf0e10cSrcweir     //------------------------------------------------
77*cdf0e10cSrcweir     //prepare text properties for multipropertyset-interface of shape
78*cdf0e10cSrcweir     tNameSequence aPropNames;
79*cdf0e10cSrcweir     tAnySequence aPropValues;
80*cdf0e10cSrcweir 
81*cdf0e10cSrcweir     uno::Reference< beans::XPropertySet > xProps( m_aAxisProperties.m_xAxisModel, uno::UNO_QUERY );
82*cdf0e10cSrcweir     PropertyMapper::getTextLabelMultiPropertyLists( xProps, aPropNames, aPropValues, false );
83*cdf0e10cSrcweir     LabelPositionHelper::doDynamicFontResize( aPropValues, aPropNames, xProps
84*cdf0e10cSrcweir         , rAxisLabelProperties.m_aFontReferenceSize );
85*cdf0e10cSrcweir 
86*cdf0e10cSrcweir     uno::Any* pColorAny = PropertyMapper::getValuePointer(aPropValues,aPropNames,C2U("CharColor"));
87*cdf0e10cSrcweir     sal_Int32 nColor = Color( COL_AUTO ).GetColor();
88*cdf0e10cSrcweir     if(pColorAny)
89*cdf0e10cSrcweir         *pColorAny >>= nColor;
90*cdf0e10cSrcweir 
91*cdf0e10cSrcweir     const uno::Sequence< rtl::OUString >* pLabels = m_bUseTextLabels? &m_aTextLabels : 0;
92*cdf0e10cSrcweir 
93*cdf0e10cSrcweir     //------------------------------------------------
94*cdf0e10cSrcweir 
95*cdf0e10cSrcweir     //TickInfo* pLastVisibleNeighbourTickInfo = NULL;
96*cdf0e10cSrcweir     sal_Int32 nTick = 0;
97*cdf0e10cSrcweir 
98*cdf0e10cSrcweir     for( TickInfo* pTickInfo = rTickIter.firstInfo()
99*cdf0e10cSrcweir         ; pTickInfo
100*cdf0e10cSrcweir         ; pTickInfo = rTickIter.nextInfo(), nTick++ )
101*cdf0e10cSrcweir     {
102*cdf0e10cSrcweir         //don't create labels which does not fit into the rhythm
103*cdf0e10cSrcweir         if( nTick%rAxisLabelProperties.nRhythm != 0)
104*cdf0e10cSrcweir             continue;
105*cdf0e10cSrcweir 
106*cdf0e10cSrcweir         //don't create labels for invisible ticks
107*cdf0e10cSrcweir         if( !pTickInfo->bPaintIt )
108*cdf0e10cSrcweir             continue;
109*cdf0e10cSrcweir 
110*cdf0e10cSrcweir         //if NO OVERLAP -> don't create labels where the
111*cdf0e10cSrcweir         //anchor position is the same as for the last label
112*cdf0e10cSrcweir         //@todo
113*cdf0e10cSrcweir 
114*cdf0e10cSrcweir         if(!pTickInfo->xTextShape.is())
115*cdf0e10cSrcweir         {
116*cdf0e10cSrcweir             //create single label
117*cdf0e10cSrcweir             bool bHasExtraColor=false;
118*cdf0e10cSrcweir             sal_Int32 nExtraColor=0;
119*cdf0e10cSrcweir 
120*cdf0e10cSrcweir             rtl::OUString aLabel;
121*cdf0e10cSrcweir             if(pLabels)
122*cdf0e10cSrcweir             {
123*cdf0e10cSrcweir                 sal_Int32 nIndex = static_cast< sal_Int32 >(pTickInfo->getUnscaledTickValue()) - 1; //first category (index 0) matches with real number 1.0
124*cdf0e10cSrcweir                 if( nIndex>=0 && nIndex<pLabels->getLength() )
125*cdf0e10cSrcweir                     aLabel = (*pLabels)[nIndex];
126*cdf0e10cSrcweir             }
127*cdf0e10cSrcweir             else
128*cdf0e10cSrcweir                 aLabel = aFixedNumberFormatter.getFormattedString( pTickInfo->getUnscaledTickValue(), nExtraColor, bHasExtraColor );
129*cdf0e10cSrcweir 
130*cdf0e10cSrcweir             if(pColorAny)
131*cdf0e10cSrcweir                 *pColorAny = uno::makeAny(bHasExtraColor?nExtraColor:nColor);
132*cdf0e10cSrcweir 
133*cdf0e10cSrcweir             double fLogicAngle = pTickInfo->getUnscaledTickValue();
134*cdf0e10cSrcweir 
135*cdf0e10cSrcweir             LabelAlignment eLabelAlignment(LABEL_ALIGN_CENTER);
136*cdf0e10cSrcweir             PolarLabelPositionHelper aPolarLabelPositionHelper(m_pPosHelper,nDimensionCount,xTarget,&aShapeFactory);
137*cdf0e10cSrcweir             sal_Int32 nScreenValueOffsetInRadiusDirection = m_aAxisLabelProperties.m_aMaximumSpaceForLabels.Height/15;
138*cdf0e10cSrcweir             awt::Point aAnchorScreenPosition2D( aPolarLabelPositionHelper.getLabelScreenPositionAndAlignmentForLogicValues(
139*cdf0e10cSrcweir                     eLabelAlignment, fLogicAngle, fLogicRadius, fLogicZ, nScreenValueOffsetInRadiusDirection ));
140*cdf0e10cSrcweir             LabelPositionHelper::changeTextAdjustment( aPropValues, aPropNames, eLabelAlignment );
141*cdf0e10cSrcweir 
142*cdf0e10cSrcweir             // #i78696# use mathematically correct rotation now
143*cdf0e10cSrcweir             const double fRotationAnglePi(rAxisLabelProperties.fRotationAngleDegree * (F_PI / -180.0));
144*cdf0e10cSrcweir 
145*cdf0e10cSrcweir             uno::Any aATransformation = ShapeFactory::makeTransformation( aAnchorScreenPosition2D, fRotationAnglePi );
146*cdf0e10cSrcweir             rtl::OUString aStackedLabel = ShapeFactory::getStackedString( aLabel, rAxisLabelProperties.bStackCharacters );
147*cdf0e10cSrcweir 
148*cdf0e10cSrcweir             pTickInfo->xTextShape = aShapeFactory.createText( xTarget, aStackedLabel, aPropNames, aPropValues, aATransformation );
149*cdf0e10cSrcweir         }
150*cdf0e10cSrcweir 
151*cdf0e10cSrcweir         //if NO OVERLAP -> remove overlapping shapes
152*cdf0e10cSrcweir         //@todo
153*cdf0e10cSrcweir     }
154*cdf0e10cSrcweir     return true;
155*cdf0e10cSrcweir }
156*cdf0e10cSrcweir 
157*cdf0e10cSrcweir void VPolarAngleAxis::createMaximumLabels()
158*cdf0e10cSrcweir {
159*cdf0e10cSrcweir     if( !prepareShapeCreation() )
160*cdf0e10cSrcweir         return;
161*cdf0e10cSrcweir 
162*cdf0e10cSrcweir     createLabels();
163*cdf0e10cSrcweir }
164*cdf0e10cSrcweir 
165*cdf0e10cSrcweir void VPolarAngleAxis::updatePositions()
166*cdf0e10cSrcweir {
167*cdf0e10cSrcweir     //todo: really only update the positions
168*cdf0e10cSrcweir 
169*cdf0e10cSrcweir     if( !prepareShapeCreation() )
170*cdf0e10cSrcweir         return;
171*cdf0e10cSrcweir 
172*cdf0e10cSrcweir     createLabels();
173*cdf0e10cSrcweir }
174*cdf0e10cSrcweir 
175*cdf0e10cSrcweir void VPolarAngleAxis::createLabels()
176*cdf0e10cSrcweir {
177*cdf0e10cSrcweir     if( !prepareShapeCreation() )
178*cdf0e10cSrcweir         return;
179*cdf0e10cSrcweir 
180*cdf0e10cSrcweir     double fLogicRadius = m_pPosHelper->getOuterLogicRadius();
181*cdf0e10cSrcweir     double fLogicZ      = 1.0;//as defined
182*cdf0e10cSrcweir 
183*cdf0e10cSrcweir     if( m_aAxisProperties.m_bDisplayLabels )
184*cdf0e10cSrcweir     {
185*cdf0e10cSrcweir         //-----------------------------------------
186*cdf0e10cSrcweir         //get the transformed screen values for all tickmarks in aAllTickInfos
187*cdf0e10cSrcweir         std::auto_ptr< TickFactory > apTickFactory( this->createTickFactory() );
188*cdf0e10cSrcweir 
189*cdf0e10cSrcweir         //create tick mark text shapes
190*cdf0e10cSrcweir         //@todo: iterate through all tick depth wich should be labeled
191*cdf0e10cSrcweir 
192*cdf0e10cSrcweir         EquidistantTickIter aTickIter( m_aAllTickInfos, m_aIncrement, 0, 0 );
193*cdf0e10cSrcweir         this->updateUnscaledValuesAtTicks( aTickIter );
194*cdf0e10cSrcweir 
195*cdf0e10cSrcweir         removeTextShapesFromTicks();
196*cdf0e10cSrcweir 
197*cdf0e10cSrcweir         AxisLabelProperties aAxisLabelProperties( m_aAxisLabelProperties );
198*cdf0e10cSrcweir         aAxisLabelProperties.bOverlapAllowed = true;
199*cdf0e10cSrcweir         while( !createTextShapes_ForAngleAxis( m_xTextTarget, aTickIter
200*cdf0e10cSrcweir                         , aAxisLabelProperties
201*cdf0e10cSrcweir                         , fLogicRadius, fLogicZ
202*cdf0e10cSrcweir                         ) )
203*cdf0e10cSrcweir         {
204*cdf0e10cSrcweir         };
205*cdf0e10cSrcweir 
206*cdf0e10cSrcweir         //no staggering for polar angle axis
207*cdf0e10cSrcweir     }
208*cdf0e10cSrcweir }
209*cdf0e10cSrcweir 
210*cdf0e10cSrcweir void VPolarAngleAxis::createShapes()
211*cdf0e10cSrcweir {
212*cdf0e10cSrcweir     if( !prepareShapeCreation() )
213*cdf0e10cSrcweir         return;
214*cdf0e10cSrcweir 
215*cdf0e10cSrcweir     double fLogicRadius = m_pPosHelper->getOuterLogicRadius();
216*cdf0e10cSrcweir     double fLogicZ      = 1.0;//as defined
217*cdf0e10cSrcweir 
218*cdf0e10cSrcweir     //-----------------------------------------
219*cdf0e10cSrcweir     //create axis main lines
220*cdf0e10cSrcweir     drawing::PointSequenceSequence aPoints(1);
221*cdf0e10cSrcweir     VPolarGrid::createLinePointSequence_ForAngleAxis( aPoints, m_aAllTickInfos, m_aIncrement, m_aScale, m_pPosHelper, fLogicRadius, fLogicZ );
222*cdf0e10cSrcweir     uno::Reference< drawing::XShape > xShape = m_pShapeFactory->createLine2D(
223*cdf0e10cSrcweir             m_xGroupShape_Shapes, aPoints, &m_aAxisProperties.m_aLineProperties );
224*cdf0e10cSrcweir     //because of this name this line will be used for marking the axis
225*cdf0e10cSrcweir     m_pShapeFactory->setShapeName( xShape, C2U("MarkHandles") );
226*cdf0e10cSrcweir 
227*cdf0e10cSrcweir     //-----------------------------------------
228*cdf0e10cSrcweir     //create labels
229*cdf0e10cSrcweir     createLabels();
230*cdf0e10cSrcweir }
231*cdf0e10cSrcweir 
232*cdf0e10cSrcweir //.............................................................................
233*cdf0e10cSrcweir } //namespace chart
234*cdf0e10cSrcweir //.............................................................................
235