1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_chart2.hxx"
26 #include "DateScaling.hxx"
27 #include <com/sun/star/chart/TimeUnit.hpp>
28 #include <rtl/math.hxx>
29 #include "com/sun/star/uno/RuntimeException.hpp"
30 
31 namespace
32 {
33 
34 static const ::rtl::OUString lcl_aServiceName_DateScaling(
35     RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.DateScaling" ));
36 static const ::rtl::OUString lcl_aServiceName_InverseDateScaling(
37     RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.InverseDateScaling" ));
38 
39 static const ::rtl::OUString lcl_aImplementationName_DateScaling(
40     RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart2.DateScaling" ));
41 static const ::rtl::OUString lcl_aImplementationName_InverseDateScaling(
42     RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart2.InverseDateScaling" ));
43 
44 static const double lcl_fNumberOfMonths = 12.0;//todo: this needs to be offered by basic tools Date class if it should be more generic
45 }
46 
47 //.............................................................................
48 namespace chart
49 {
50 //.............................................................................
51 using namespace ::com::sun::star;
52 using namespace ::com::sun::star::chart2;
53 using ::com::sun::star::chart::TimeUnit::DAY;
54 using ::com::sun::star::chart::TimeUnit::MONTH;
55 using ::com::sun::star::chart::TimeUnit::YEAR;
56 
DateScaling(const Date & rNullDate,sal_Int32 nTimeUnit,bool bShifted)57 DateScaling::DateScaling( const Date& rNullDate, sal_Int32 nTimeUnit, bool bShifted )
58         : m_aNullDate( rNullDate )
59         , m_nTimeUnit( nTimeUnit )
60         , m_bShifted( bShifted )
61 {
62 }
63 
~DateScaling()64 DateScaling::~DateScaling()
65 {
66 }
67 
doScaling(double value)68 double SAL_CALL DateScaling::doScaling( double value )
69     throw (uno::RuntimeException)
70 {
71     double fResult(value);
72     if( ::rtl::math::isNan( value ) || ::rtl::math::isInf( value ) )
73         ::rtl::math::setNan( & fResult );
74     else
75     {
76         Date aDate(m_aNullDate);
77         aDate += static_cast<long>(::rtl::math::approxFloor(value));
78         switch( m_nTimeUnit )
79         {
80             case DAY:
81                 fResult = value;
82                 if(m_bShifted)
83                     fResult+=0.5;
84                 break;
85             case YEAR:
86             case MONTH:
87             default:
88                 fResult = aDate.GetYear();
89                 fResult *= lcl_fNumberOfMonths;//asssuming equal count of months in each year
90                 fResult += aDate.GetMonth();
91 
92                 double fDayOfMonth = aDate.GetDay();
93                 fDayOfMonth -= 1.0;
94                 double fDaysInMonth = aDate.GetDaysInMonth();
95                 fResult += fDayOfMonth/fDaysInMonth;
96                 if(m_bShifted)
97                 {
98                     if( YEAR==m_nTimeUnit )
99                         fResult += 0.5*lcl_fNumberOfMonths;
100                     else
101                         fResult += 0.5;
102                 }
103                 break;
104         }
105     }
106     return fResult;
107 }
108 
getInverseScaling()109 uno::Reference< XScaling > SAL_CALL DateScaling::getInverseScaling()
110     throw (uno::RuntimeException)
111 {
112     return new InverseDateScaling( m_aNullDate, m_nTimeUnit, m_bShifted );
113 }
114 
getServiceName()115 ::rtl::OUString SAL_CALL DateScaling::getServiceName()
116     throw (uno::RuntimeException)
117 {
118     return lcl_aServiceName_DateScaling;
119 }
120 
getSupportedServiceNames_Static()121 uno::Sequence< ::rtl::OUString > DateScaling::getSupportedServiceNames_Static()
122 {
123     return uno::Sequence< ::rtl::OUString >( & lcl_aServiceName_DateScaling, 1 );
124 }
125 
126 // implement XServiceInfo methods basing upon getSupportedServiceNames_Static
APPHELPER_XSERVICEINFO_IMPL(DateScaling,lcl_aServiceName_DateScaling)127 APPHELPER_XSERVICEINFO_IMPL( DateScaling, lcl_aServiceName_DateScaling )
128 
129 // ----------------------------------------
130 
131 InverseDateScaling::InverseDateScaling( const Date& rNullDate, sal_Int32 nTimeUnit, bool bShifted )
132         : m_aNullDate( rNullDate )
133         , m_nTimeUnit( nTimeUnit )
134         , m_bShifted( bShifted )
135 {
136 }
137 
~InverseDateScaling()138 InverseDateScaling::~InverseDateScaling()
139 {
140 }
141 
doScaling(double value)142 double SAL_CALL InverseDateScaling::doScaling( double value )
143     throw (uno::RuntimeException)
144 {
145     double fResult(value);
146     if( ::rtl::math::isNan( value ) || ::rtl::math::isInf( value ) )
147         ::rtl::math::setNan( & fResult );
148     else
149     {
150         switch( m_nTimeUnit )
151         {
152             case DAY:
153                 if(m_bShifted)
154                     value -= 0.5;
155                 fResult = value;
156                 break;
157             case YEAR:
158             case MONTH:
159             default:
160                 //Date aDate(m_aNullDate);
161                 if(m_bShifted)
162                 {
163                     if( YEAR==m_nTimeUnit )
164                         value -= 0.5*lcl_fNumberOfMonths;
165                     else
166                         value -= 0.5;
167                 }
168                 Date aDate;
169                 double fYear = ::rtl::math::approxFloor(value/lcl_fNumberOfMonths);
170                 double fMonth = ::rtl::math::approxFloor(value-(fYear*lcl_fNumberOfMonths));
171                 if( fMonth==0.0 )
172                 {
173                     fYear--;
174                     fMonth=12.0;
175                 }
176                 aDate.SetYear( static_cast<sal_uInt16>(fYear) );
177                 aDate.SetMonth( static_cast<sal_uInt16>(fMonth) );
178                 aDate.SetDay( 1 );
179                 double fMonthCount = (fYear*lcl_fNumberOfMonths)+fMonth;
180                 double fDay = (value-fMonthCount)*aDate.GetDaysInMonth();
181                 fDay += 1.0;
182                 aDate.SetDay( static_cast<sal_uInt16>(::rtl::math::round(fDay)) );
183                 fResult = aDate - m_aNullDate;
184                 break;
185         }
186     }
187     return fResult;
188 }
189 
getInverseScaling()190 uno::Reference< XScaling > SAL_CALL InverseDateScaling::getInverseScaling()
191     throw (uno::RuntimeException)
192 {
193     return new DateScaling( m_aNullDate, m_nTimeUnit, m_bShifted );
194 }
195 
getServiceName()196 ::rtl::OUString SAL_CALL InverseDateScaling::getServiceName()
197     throw (uno::RuntimeException)
198 {
199     return lcl_aServiceName_InverseDateScaling;
200 }
201 
getSupportedServiceNames_Static()202 uno::Sequence< ::rtl::OUString > InverseDateScaling::getSupportedServiceNames_Static()
203 {
204     return uno::Sequence< ::rtl::OUString >( & lcl_aServiceName_InverseDateScaling, 1 );
205 }
206 
207 // implement XServiceInfo methods basing upon getSupportedServiceNames_Static
208 APPHELPER_XSERVICEINFO_IMPL( InverseDateScaling, lcl_aServiceName_InverseDateScaling )
209 
210 //.............................................................................
211 } //namespace chart
212 //.............................................................................
213