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 "DateScaling.hxx"
31 #include <com/sun/star/chart/TimeUnit.hpp>
32 #include <rtl/math.hxx>
33 #include "com/sun/star/uno/RuntimeException.hpp"
34 
35 namespace
36 {
37 
38 static const ::rtl::OUString lcl_aServiceName_DateScaling(
39     RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.DateScaling" ));
40 static const ::rtl::OUString lcl_aServiceName_InverseDateScaling(
41     RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.InverseDateScaling" ));
42 
43 static const ::rtl::OUString lcl_aImplementationName_DateScaling(
44     RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart2.DateScaling" ));
45 static const ::rtl::OUString lcl_aImplementationName_InverseDateScaling(
46     RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart2.InverseDateScaling" ));
47 
48 static const double lcl_fNumberOfMonths = 12.0;//todo: this needs to be offered by basic tools Date class if it should be more generic
49 }
50 
51 //.............................................................................
52 namespace chart
53 {
54 //.............................................................................
55 using namespace ::com::sun::star;
56 using namespace ::com::sun::star::chart2;
57 using ::com::sun::star::chart::TimeUnit::DAY;
58 using ::com::sun::star::chart::TimeUnit::MONTH;
59 using ::com::sun::star::chart::TimeUnit::YEAR;
60 
61 DateScaling::DateScaling( const Date& rNullDate, sal_Int32 nTimeUnit, bool bShifted )
62         : m_aNullDate( rNullDate )
63         , m_nTimeUnit( nTimeUnit )
64         , m_bShifted( bShifted )
65 {
66 }
67 
68 DateScaling::~DateScaling()
69 {
70 }
71 
72 double SAL_CALL DateScaling::doScaling( double value )
73     throw (uno::RuntimeException)
74 {
75     double fResult(value);
76     if( ::rtl::math::isNan( value ) || ::rtl::math::isInf( value ) )
77         ::rtl::math::setNan( & fResult );
78     else
79     {
80         Date aDate(m_aNullDate);
81         aDate += static_cast<long>(::rtl::math::approxFloor(value));
82         switch( m_nTimeUnit )
83         {
84             case DAY:
85                 fResult = value;
86                 if(m_bShifted)
87                     fResult+=0.5;
88                 break;
89             case YEAR:
90             case MONTH:
91             default:
92                 fResult = aDate.GetYear();
93                 fResult *= lcl_fNumberOfMonths;//asssuming equal count of months in each year
94                 fResult += aDate.GetMonth();
95 
96                 double fDayOfMonth = aDate.GetDay();
97                 fDayOfMonth -= 1.0;
98                 double fDaysInMonth = aDate.GetDaysInMonth();
99                 fResult += fDayOfMonth/fDaysInMonth;
100                 if(m_bShifted)
101                 {
102                     if( YEAR==m_nTimeUnit )
103                         fResult += 0.5*lcl_fNumberOfMonths;
104                     else
105                         fResult += 0.5;
106                 }
107                 break;
108         }
109     }
110     return fResult;
111 }
112 
113 uno::Reference< XScaling > SAL_CALL DateScaling::getInverseScaling()
114     throw (uno::RuntimeException)
115 {
116     return new InverseDateScaling( m_aNullDate, m_nTimeUnit, m_bShifted );
117 }
118 
119 ::rtl::OUString SAL_CALL DateScaling::getServiceName()
120     throw (uno::RuntimeException)
121 {
122     return lcl_aServiceName_DateScaling;
123 }
124 
125 uno::Sequence< ::rtl::OUString > DateScaling::getSupportedServiceNames_Static()
126 {
127     return uno::Sequence< ::rtl::OUString >( & lcl_aServiceName_DateScaling, 1 );
128 }
129 
130 // implement XServiceInfo methods basing upon getSupportedServiceNames_Static
131 APPHELPER_XSERVICEINFO_IMPL( DateScaling, lcl_aServiceName_DateScaling )
132 
133 // ----------------------------------------
134 
135 InverseDateScaling::InverseDateScaling( const Date& rNullDate, sal_Int32 nTimeUnit, bool bShifted )
136         : m_aNullDate( rNullDate )
137         , m_nTimeUnit( nTimeUnit )
138         , m_bShifted( bShifted )
139 {
140 }
141 
142 InverseDateScaling::~InverseDateScaling()
143 {
144 }
145 
146 double SAL_CALL InverseDateScaling::doScaling( double value )
147     throw (uno::RuntimeException)
148 {
149     double fResult(value);
150     if( ::rtl::math::isNan( value ) || ::rtl::math::isInf( value ) )
151         ::rtl::math::setNan( & fResult );
152     else
153     {
154         switch( m_nTimeUnit )
155         {
156             case DAY:
157                 if(m_bShifted)
158                     value -= 0.5;
159                 fResult = value;
160                 break;
161             case YEAR:
162             case MONTH:
163             default:
164                 //Date aDate(m_aNullDate);
165                 if(m_bShifted)
166                 {
167                     if( YEAR==m_nTimeUnit )
168                         value -= 0.5*lcl_fNumberOfMonths;
169                     else
170                         value -= 0.5;
171                 }
172                 Date aDate;
173                 double fYear = ::rtl::math::approxFloor(value/lcl_fNumberOfMonths);
174                 double fMonth = ::rtl::math::approxFloor(value-(fYear*lcl_fNumberOfMonths));
175                 if( fMonth==0.0 )
176                 {
177                     fYear--;
178                     fMonth=12.0;
179                 }
180                 aDate.SetYear( static_cast<sal_uInt16>(fYear) );
181                 aDate.SetMonth( static_cast<sal_uInt16>(fMonth) );
182                 aDate.SetDay( 1 );
183                 double fMonthCount = (fYear*lcl_fNumberOfMonths)+fMonth;
184                 double fDay = (value-fMonthCount)*aDate.GetDaysInMonth();
185                 fDay += 1.0;
186                 aDate.SetDay( static_cast<sal_uInt16>(::rtl::math::round(fDay)) );
187                 fResult = aDate - m_aNullDate;
188                 break;
189         }
190     }
191     return fResult;
192 }
193 
194 uno::Reference< XScaling > SAL_CALL InverseDateScaling::getInverseScaling()
195     throw (uno::RuntimeException)
196 {
197     return new DateScaling( m_aNullDate, m_nTimeUnit, m_bShifted );
198 }
199 
200 ::rtl::OUString SAL_CALL InverseDateScaling::getServiceName()
201     throw (uno::RuntimeException)
202 {
203     return lcl_aServiceName_InverseDateScaling;
204 }
205 
206 uno::Sequence< ::rtl::OUString > InverseDateScaling::getSupportedServiceNames_Static()
207 {
208     return uno::Sequence< ::rtl::OUString >( & lcl_aServiceName_InverseDateScaling, 1 );
209 }
210 
211 // implement XServiceInfo methods basing upon getSupportedServiceNames_Static
212 APPHELPER_XSERVICEINFO_IMPL( InverseDateScaling, lcl_aServiceName_InverseDateScaling )
213 
214 //.............................................................................
215 } //namespace chart
216 //.............................................................................
217