xref: /aoo41x/main/sc/source/ui/unoobj/addruno.cxx (revision cdf0e10c)
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_sc.hxx"
30 
31 
32 
33 #include <com/sun/star/table/CellAddress.hpp>
34 #include <com/sun/star/table/CellRangeAddress.hpp>
35 
36 #include <svl/itemprop.hxx>
37 
38 #include "docsh.hxx"
39 #include "unonames.hxx"
40 #include "unoguard.hxx"
41 #include "miscuno.hxx"
42 #include "convuno.hxx"
43 #include "addruno.hxx"
44 
45 using namespace com::sun::star;
46 
47 //------------------------------------------------------------------------
48 
49 ScAddressConversionObj::ScAddressConversionObj(ScDocShell* pDocSh, sal_Bool bForRange) :
50     pDocShell( pDocSh ),
51     nRefSheet( 0 ),
52     bIsRange( bForRange )
53 {
54     pDocShell->GetDocument()->AddUnoObject(*this);
55 }
56 
57 ScAddressConversionObj::~ScAddressConversionObj()
58 {
59     if (pDocShell)
60         pDocShell->GetDocument()->RemoveUnoObject(*this);
61 }
62 
63 void ScAddressConversionObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
64 {
65     if ( rHint.ISA( SfxSimpleHint ) &&
66             ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
67     {
68         pDocShell = NULL;       // invalid
69     }
70 }
71 
72 sal_Bool ScAddressConversionObj::ParseUIString( const String& rUIString, ::formula::FormulaGrammar::AddressConvention eConv )
73 {
74     if (!pDocShell)
75         return sal_False;
76 
77     ScDocument* pDoc = pDocShell->GetDocument();
78     sal_Bool bSuccess = sal_False;
79     if ( bIsRange )
80     {
81         sal_uInt16 nResult = aRange.ParseAny( rUIString, pDoc, eConv );
82         if ( nResult & SCA_VALID )
83         {
84             if ( ( nResult & SCA_TAB_3D ) == 0 )
85                 aRange.aStart.SetTab( static_cast<SCTAB>(nRefSheet) );
86             if ( ( nResult & SCA_TAB2_3D ) == 0 )
87                 aRange.aEnd.SetTab( aRange.aStart.Tab() );
88             // different sheets are not supported in CellRangeAddress
89             if ( aRange.aStart.Tab() == aRange.aEnd.Tab() )
90                 bSuccess = sal_True;
91         }
92     }
93     else
94     {
95         sal_uInt16 nResult = aRange.aStart.Parse( rUIString, pDoc, eConv );
96         if ( nResult & SCA_VALID )
97         {
98             if ( ( nResult & SCA_TAB_3D ) == 0 )
99                 aRange.aStart.SetTab( static_cast<SCTAB>(nRefSheet) );
100             bSuccess = sal_True;
101         }
102     }
103     return bSuccess;
104 }
105 
106 // XPropertySet
107 
108 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScAddressConversionObj::getPropertySetInfo()
109                                                         throw(uno::RuntimeException)
110 {
111     ScUnoGuard aGuard;
112 
113     if ( bIsRange )
114     {
115         static SfxItemPropertyMapEntry aPropertyMap[] =
116         {
117             {MAP_CHAR_LEN(SC_UNONAME_ADDRESS),  0,  &getCppuType((table::CellRangeAddress*)0), 0, 0 },
118             {MAP_CHAR_LEN(SC_UNONAME_PERSREPR), 0,  &getCppuType((rtl::OUString*)0),    0, 0 },
119             {MAP_CHAR_LEN(SC_UNONAME_REFSHEET), 0,  &getCppuType((sal_Int32*)0),        0, 0 },
120             {MAP_CHAR_LEN(SC_UNONAME_UIREPR),   0,  &getCppuType((rtl::OUString*)0),    0, 0 },
121             {MAP_CHAR_LEN(SC_UNONAME_XLA1REPR), 0,  &getCppuType((rtl::OUString*)0),    0, 0 },
122             {0,0,0,0,0,0}
123         };
124         static uno::Reference<beans::XPropertySetInfo> aRef(new SfxItemPropertySetInfo( aPropertyMap ));
125         return aRef;
126     }
127     else
128     {
129         static SfxItemPropertyMapEntry aPropertyMap[] =
130         {
131             {MAP_CHAR_LEN(SC_UNONAME_ADDRESS),  0,  &getCppuType((table::CellAddress*)0), 0, 0 },
132             {MAP_CHAR_LEN(SC_UNONAME_PERSREPR), 0,  &getCppuType((rtl::OUString*)0),    0, 0 },
133             {MAP_CHAR_LEN(SC_UNONAME_REFSHEET), 0,  &getCppuType((sal_Int32*)0),        0, 0 },
134             {MAP_CHAR_LEN(SC_UNONAME_UIREPR),   0,  &getCppuType((rtl::OUString*)0),    0, 0 },
135             {MAP_CHAR_LEN(SC_UNONAME_XLA1REPR), 0,  &getCppuType((rtl::OUString*)0),    0, 0 },
136             {0,0,0,0,0,0}
137         };
138         static uno::Reference<beans::XPropertySetInfo> aRef(new SfxItemPropertySetInfo( aPropertyMap ));
139         return aRef;
140     }
141 }
142 
143 void SAL_CALL ScAddressConversionObj::setPropertyValue( const rtl::OUString& aPropertyName, const uno::Any& aValue )
144                 throw(beans::UnknownPropertyException, beans::PropertyVetoException,
145                         lang::IllegalArgumentException, lang::WrappedTargetException,
146                         uno::RuntimeException)
147 {
148     if ( !pDocShell )
149         throw uno::RuntimeException();
150 
151     sal_Bool bSuccess = sal_False;
152     String aNameStr(aPropertyName);
153     if ( aNameStr.EqualsAscii( SC_UNONAME_ADDRESS ) )
154     {
155         //  read the cell/range address from API struct
156         if ( bIsRange )
157         {
158             table::CellRangeAddress aRangeAddress;
159             if ( aValue >>= aRangeAddress )
160             {
161                 ScUnoConversion::FillScRange( aRange, aRangeAddress );
162                 bSuccess = sal_True;
163             }
164         }
165         else
166         {
167             table::CellAddress aCellAddress;
168             if ( aValue >>= aCellAddress )
169             {
170                 ScUnoConversion::FillScAddress( aRange.aStart, aCellAddress );
171                 bSuccess = sal_True;
172             }
173         }
174     }
175     else if ( aNameStr.EqualsAscii( SC_UNONAME_REFSHEET ) )
176     {
177         //  set the reference sheet
178         sal_Int32 nIntVal = 0;
179         if ( aValue >>= nIntVal )
180         {
181             nRefSheet = nIntVal;
182             bSuccess = sal_True;
183         }
184     }
185     else if ( aNameStr.EqualsAscii( SC_UNONAME_UIREPR ) )
186     {
187         //  parse the UI representation string
188         rtl::OUString sRepresentation;
189         if (aValue >>= sRepresentation)
190         {
191             String aUIString = sRepresentation;
192             bSuccess = ParseUIString( aUIString );
193         }
194     }
195     else if ( aNameStr.EqualsAscii( SC_UNONAME_PERSREPR ) || aNameStr.EqualsAscii( SC_UNONAME_XLA1REPR ) )
196     {
197         ::formula::FormulaGrammar::AddressConvention eConv = aNameStr.EqualsAscii( SC_UNONAME_XLA1REPR ) ?
198             ::formula::FormulaGrammar::CONV_XL_A1 : ::formula::FormulaGrammar::CONV_OOO;
199 
200         //  parse the file format string
201         rtl::OUString sRepresentation;
202         if (aValue >>= sRepresentation)
203         {
204             String aUIString(sRepresentation);
205 
206             //  cell or range: strip a single "." at the start
207             if ( aUIString.GetChar(0) == (sal_Unicode) '.' )
208                 aUIString.Erase( 0, 1 );
209 
210             if ( bIsRange )
211             {
212                 //  range: also strip a "." after the last colon
213                 sal_Int32 nColon = rtl::OUString(aUIString).lastIndexOf( (sal_Unicode) ':' );
214                 if ( nColon >= 0 && nColon < aUIString.Len() - 1 &&
215                      aUIString.GetChar((xub_StrLen)nColon+1) == (sal_Unicode) '.' )
216                     aUIString.Erase( (xub_StrLen)nColon+1, 1 );
217             }
218 
219             //  parse the rest like a UI string
220             bSuccess = ParseUIString( aUIString, eConv );
221         }
222     }
223     else
224         throw beans::UnknownPropertyException();
225 
226     if ( !bSuccess )
227         throw lang::IllegalArgumentException();
228 }
229 
230 uno::Any SAL_CALL ScAddressConversionObj::getPropertyValue( const rtl::OUString& aPropertyName )
231                 throw(beans::UnknownPropertyException, lang::WrappedTargetException,
232                         uno::RuntimeException)
233 {
234     if ( !pDocShell )
235         throw uno::RuntimeException();
236 
237     ScDocument* pDoc = pDocShell->GetDocument();
238     uno::Any aRet;
239 
240     String aNameStr(aPropertyName);
241     if ( aNameStr.EqualsAscii( SC_UNONAME_ADDRESS ) )
242     {
243         if ( bIsRange )
244         {
245             table::CellRangeAddress aRangeAddress;
246             ScUnoConversion::FillApiRange( aRangeAddress, aRange );
247             aRet <<= aRangeAddress;
248         }
249         else
250         {
251             table::CellAddress aCellAddress;
252             ScUnoConversion::FillApiAddress( aCellAddress, aRange.aStart );
253             aRet <<= aCellAddress;
254         }
255     }
256     else if ( aNameStr.EqualsAscii( SC_UNONAME_REFSHEET ) )
257     {
258         aRet <<= nRefSheet;
259     }
260     else if ( aNameStr.EqualsAscii( SC_UNONAME_UIREPR ) )
261     {
262         //  generate UI representation string - include sheet only if different from ref sheet
263         String aFormatStr;
264         sal_uInt16 nFlags = SCA_VALID;
265         if ( aRange.aStart.Tab() != nRefSheet )
266             nFlags |= SCA_TAB_3D;
267         if ( bIsRange )
268             aRange.Format( aFormatStr, nFlags, pDoc );
269         else
270             aRange.aStart.Format( aFormatStr, nFlags, pDoc );
271         aRet <<= rtl::OUString( aFormatStr );
272     }
273     else if ( aNameStr.EqualsAscii( SC_UNONAME_PERSREPR ) || aNameStr.EqualsAscii( SC_UNONAME_XLA1REPR ) )
274     {
275         ::formula::FormulaGrammar::AddressConvention eConv = aNameStr.EqualsAscii( SC_UNONAME_XLA1REPR ) ?
276             ::formula::FormulaGrammar::CONV_XL_A1 : ::formula::FormulaGrammar::CONV_OOO;
277 
278         //  generate file format string - always include sheet
279         String aFormatStr;
280         aRange.aStart.Format( aFormatStr, SCA_VALID | SCA_TAB_3D, pDoc, eConv );
281         if ( bIsRange )
282         {
283             //  manually concatenate range so both parts always have the sheet name
284             aFormatStr.Append( (sal_Unicode) ':' );
285             String aSecond;
286             sal_uInt16 nFlags = SCA_VALID;
287             if( eConv != ::formula::FormulaGrammar::CONV_XL_A1 )
288                 nFlags |= SCA_TAB_3D;
289             aRange.aEnd.Format( aSecond, nFlags, pDoc, eConv );
290             aFormatStr.Append( aSecond );
291         }
292         aRet <<= rtl::OUString( aFormatStr );
293     }
294     else
295         throw beans::UnknownPropertyException();
296 
297     return aRet;
298 }
299 
300 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScAddressConversionObj )
301 
302 // lang::XServiceInfo
303 
304 rtl::OUString SAL_CALL ScAddressConversionObj::getImplementationName() throw(uno::RuntimeException)
305 {
306     return rtl::OUString::createFromAscii( "ScAddressConversionObj" );
307 }
308 
309 sal_Bool SAL_CALL ScAddressConversionObj::supportsService( const rtl::OUString& rServiceName )
310                                                     throw(uno::RuntimeException)
311 {
312     String aServiceStr( rServiceName );
313     return aServiceStr.EqualsAscii( bIsRange ? SC_SERVICENAME_RANGEADDRESS
314                                              : SC_SERVICENAME_CELLADDRESS );
315 }
316 
317 uno::Sequence<rtl::OUString> SAL_CALL ScAddressConversionObj::getSupportedServiceNames()
318                                                     throw(uno::RuntimeException)
319 {
320     uno::Sequence<rtl::OUString> aRet(1);
321     rtl::OUString* pArray = aRet.getArray();
322     pArray[0] = rtl::OUString::createFromAscii( bIsRange ? SC_SERVICENAME_RANGEADDRESS
323                                                          : SC_SERVICENAME_CELLADDRESS );
324     return aRet;
325 }
326 
327