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