1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20 #include <com/sun/star/table/CellAddress.hpp>
21 #include <com/sun/star/table/CellRangeAddress.hpp>
22 #include <cppuhelper/supportsservice.hxx>
23
24 #include <svl/itemprop.hxx>
25 #include <vcl/svapp.hxx>
26
27 #include <docsh.hxx>
28 #include <unonames.hxx>
29 #include <miscuno.hxx>
30 #include <convuno.hxx>
31 #include <addruno.hxx>
32
33 using namespace com::sun::star;
34
ScAddressConversionObj(ScDocShell * pDocSh,bool _bIsRange)35 ScAddressConversionObj::ScAddressConversionObj(ScDocShell* pDocSh, bool _bIsRange) :
36 pDocShell( pDocSh ),
37 nRefSheet( 0 ),
38 bIsRange( _bIsRange )
39 {
40 pDocShell->GetDocument().AddUnoObject(*this);
41 }
42
~ScAddressConversionObj()43 ScAddressConversionObj::~ScAddressConversionObj()
44 {
45 SolarMutexGuard g;
46
47 if (pDocShell)
48 pDocShell->GetDocument().RemoveUnoObject(*this);
49 }
50
Notify(SfxBroadcaster &,const SfxHint & rHint)51 void ScAddressConversionObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
52 {
53 if ( rHint.GetId() == SfxHintId::Dying )
54 {
55 pDocShell = nullptr; // invalid
56 }
57 }
58
ParseUIString(const OUString & rUIString,::formula::FormulaGrammar::AddressConvention eConv)59 bool ScAddressConversionObj::ParseUIString( const OUString& rUIString, ::formula::FormulaGrammar::AddressConvention eConv )
60 {
61 if (!pDocShell)
62 return false;
63
64 ScDocument& rDoc = pDocShell->GetDocument();
65 bool bSuccess = false;
66 if ( bIsRange )
67 {
68 ScRefFlags nResult = aRange.ParseAny( rUIString, &rDoc, eConv );
69 if ( nResult & ScRefFlags::VALID )
70 {
71 if ( ( nResult & ScRefFlags::TAB_3D ) == ScRefFlags::ZERO )
72 aRange.aStart.SetTab( static_cast<SCTAB>(nRefSheet) );
73 if ( ( nResult & ScRefFlags::TAB2_3D ) == ScRefFlags::ZERO )
74 aRange.aEnd.SetTab( aRange.aStart.Tab() );
75 // different sheets are not supported in CellRangeAddress
76 if ( aRange.aStart.Tab() == aRange.aEnd.Tab() )
77 bSuccess = true;
78 }
79 }
80 else
81 {
82 ScRefFlags nResult = aRange.aStart.Parse( rUIString, &rDoc, eConv );
83 if ( nResult & ScRefFlags::VALID )
84 {
85 if ( ( nResult & ScRefFlags::TAB_3D ) == ScRefFlags::ZERO )
86 aRange.aStart.SetTab( static_cast<SCTAB>(nRefSheet) );
87 bSuccess = true;
88 }
89 }
90 return bSuccess;
91 }
92
93 // XPropertySet
94
getPropertySetInfo()95 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScAddressConversionObj::getPropertySetInfo()
96 {
97 SolarMutexGuard aGuard;
98
99 if ( bIsRange )
100 {
101 static const SfxItemPropertyMapEntry aPropertyMap[] =
102 {
103 { OUString(SC_UNONAME_ADDRESS), 0, cppu::UnoType<table::CellRangeAddress>::get(), 0, 0 },
104 { OUString(SC_UNONAME_PERSREPR), 0, cppu::UnoType<OUString>::get(), 0, 0 },
105 { OUString(SC_UNONAME_XLA1REPR), 0, cppu::UnoType<OUString>::get(), 0, 0 },
106 { OUString(SC_UNONAME_REFSHEET), 0, cppu::UnoType<sal_Int32>::get(), 0, 0 },
107 { OUString(SC_UNONAME_UIREPR), 0, cppu::UnoType<OUString>::get(), 0, 0 },
108 { OUString(SC_UNONAME_XLA1REPR), 0, cppu::UnoType<OUString>::get(), 0, 0 },
109 { OUString(), 0, css::uno::Type(), 0, 0 }
110 };
111 static uno::Reference<beans::XPropertySetInfo> aRef(new SfxItemPropertySetInfo( aPropertyMap ));
112 return aRef;
113 }
114 else
115 {
116 static const SfxItemPropertyMapEntry aPropertyMap[] =
117 {
118 { OUString(SC_UNONAME_ADDRESS), 0, cppu::UnoType<table::CellAddress>::get(), 0, 0 },
119 { OUString(SC_UNONAME_PERSREPR), 0, cppu::UnoType<OUString>::get(), 0, 0 },
120 { OUString(SC_UNONAME_XLA1REPR), 0, cppu::UnoType<OUString>::get(), 0, 0 },
121 { OUString(SC_UNONAME_REFSHEET), 0, cppu::UnoType<sal_Int32>::get(), 0, 0 },
122 { OUString(SC_UNONAME_UIREPR), 0, cppu::UnoType<OUString>::get(), 0, 0 },
123 { OUString(SC_UNONAME_XLA1REPR), 0, cppu::UnoType<OUString>::get(), 0, 0 },
124 { OUString(), 0, css::uno::Type(), 0, 0 }
125 };
126 static uno::Reference<beans::XPropertySetInfo> aRef(new SfxItemPropertySetInfo( aPropertyMap ));
127 return aRef;
128 }
129 }
130
setPropertyValue(const OUString & aPropertyName,const uno::Any & aValue)131 void SAL_CALL ScAddressConversionObj::setPropertyValue( const OUString& aPropertyName, const uno::Any& aValue )
132 {
133 if ( !pDocShell )
134 throw uno::RuntimeException();
135
136 bool bSuccess = false;
137 if ( aPropertyName == SC_UNONAME_ADDRESS )
138 {
139 // read the cell/range address from API struct
140 if ( bIsRange )
141 {
142 table::CellRangeAddress aRangeAddress;
143 if ( aValue >>= aRangeAddress )
144 {
145 ScUnoConversion::FillScRange( aRange, aRangeAddress );
146 bSuccess = true;
147 }
148 }
149 else
150 {
151 table::CellAddress aCellAddress;
152 if ( aValue >>= aCellAddress )
153 {
154 ScUnoConversion::FillScAddress( aRange.aStart, aCellAddress );
155 bSuccess = true;
156 }
157 }
158 }
159 else if ( aPropertyName == SC_UNONAME_REFSHEET )
160 {
161 // set the reference sheet
162 sal_Int32 nIntVal = 0;
163 if ( aValue >>= nIntVal )
164 {
165 nRefSheet = nIntVal;
166 bSuccess = true;
167 }
168 }
169 else if ( aPropertyName == SC_UNONAME_UIREPR )
170 {
171 // parse the UI representation string
172 OUString sRepresentation;
173 if (aValue >>= sRepresentation)
174 {
175 bSuccess = ParseUIString( sRepresentation );
176 }
177 }
178 else if ( aPropertyName == SC_UNONAME_PERSREPR || aPropertyName == SC_UNONAME_XLA1REPR )
179 {
180 ::formula::FormulaGrammar::AddressConvention eConv = aPropertyName == SC_UNONAME_XLA1REPR ?
181 ::formula::FormulaGrammar::CONV_XL_A1 : ::formula::FormulaGrammar::CONV_OOO;
182
183 // parse the file format string
184 OUString sRepresentation;
185 if (aValue >>= sRepresentation)
186 {
187 OUString aUIString(sRepresentation);
188
189 // cell or range: strip a single "." at the start
190 if ( aUIString[0]== '.' )
191 aUIString = aUIString.copy( 1 );
192
193 if ( bIsRange )
194 {
195 // range: also strip a "." after the last colon
196 sal_Int32 nColon = aUIString.lastIndexOf( ':' );
197 if ( nColon >= 0 && nColon < aUIString.getLength() - 1 &&
198 aUIString[nColon+1] == '.' )
199 aUIString = aUIString.replaceAt( nColon+1, 1, "" );
200 }
201
202 // parse the rest like a UI string
203 bSuccess = ParseUIString( aUIString, eConv );
204 }
205 }
206 else
207 throw beans::UnknownPropertyException(aPropertyName);
208
209 if ( !bSuccess )
210 throw lang::IllegalArgumentException();
211 }
212
getPropertyValue(const OUString & aPropertyName)213 uno::Any SAL_CALL ScAddressConversionObj::getPropertyValue( const OUString& aPropertyName )
214 {
215 if ( !pDocShell )
216 throw uno::RuntimeException();
217
218 ScDocument& rDoc = pDocShell->GetDocument();
219 uno::Any aRet;
220
221 if ( aPropertyName == SC_UNONAME_ADDRESS )
222 {
223 if ( bIsRange )
224 {
225 table::CellRangeAddress aRangeAddress;
226 ScUnoConversion::FillApiRange( aRangeAddress, aRange );
227 aRet <<= aRangeAddress;
228 }
229 else
230 {
231 table::CellAddress aCellAddress;
232 ScUnoConversion::FillApiAddress( aCellAddress, aRange.aStart );
233 aRet <<= aCellAddress;
234 }
235 }
236 else if ( aPropertyName == SC_UNONAME_REFSHEET )
237 {
238 aRet <<= nRefSheet;
239 }
240 else if ( aPropertyName == SC_UNONAME_UIREPR )
241 {
242 // generate UI representation string - include sheet only if different from ref sheet
243 OUString aFormatStr;
244 ScRefFlags nFlags = ScRefFlags::VALID;
245 if ( aRange.aStart.Tab() != nRefSheet )
246 nFlags |= ScRefFlags::TAB_3D;
247 if ( bIsRange )
248 aFormatStr = aRange.Format(nFlags, &rDoc);
249 else
250 aFormatStr = aRange.aStart.Format(nFlags, &rDoc);
251 aRet <<= aFormatStr;
252 }
253 else if ( aPropertyName == SC_UNONAME_PERSREPR || aPropertyName == SC_UNONAME_XLA1REPR )
254 {
255 ::formula::FormulaGrammar::AddressConvention eConv = aPropertyName == SC_UNONAME_XLA1REPR ?
256 ::formula::FormulaGrammar::CONV_XL_A1 : ::formula::FormulaGrammar::CONV_OOO;
257
258 // generate file format string - always include sheet
259 OUString aFormatStr(aRange.aStart.Format(ScRefFlags::VALID | ScRefFlags::TAB_3D, &rDoc, eConv));
260 if ( bIsRange )
261 {
262 // manually concatenate range so both parts always have the sheet name
263 aFormatStr += ":";
264 ScRefFlags nFlags = ScRefFlags::VALID;
265 if( eConv != ::formula::FormulaGrammar::CONV_XL_A1 )
266 nFlags |= ScRefFlags::TAB_3D;
267 OUString aSecond(aRange.aEnd.Format(nFlags, &rDoc, eConv));
268 aFormatStr += aSecond ;
269 }
270 aRet <<= aFormatStr;
271 }
272 else
273 throw beans::UnknownPropertyException(aPropertyName);
274
275 return aRet;
276 }
277
SC_IMPL_DUMMY_PROPERTY_LISTENER(ScAddressConversionObj)278 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScAddressConversionObj )
279
280 // lang::XServiceInfo
281
282 OUString SAL_CALL ScAddressConversionObj::getImplementationName()
283 {
284 return "ScAddressConversionObj";
285 }
286
supportsService(const OUString & rServiceName)287 sal_Bool SAL_CALL ScAddressConversionObj::supportsService( const OUString& rServiceName )
288 {
289 return cppu::supportsService(this, rServiceName);
290 }
291
getSupportedServiceNames()292 uno::Sequence<OUString> SAL_CALL ScAddressConversionObj::getSupportedServiceNames()
293 {
294 if (bIsRange)
295 return {SC_SERVICENAME_RANGEADDRESS};
296 else
297 return {SC_SERVICENAME_CELLADDRESS};
298 }
299
300 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
301