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