Line data Source code
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 "scitems.hxx"
21 : #include <svl/intitem.hxx>
22 : #include <svl/zforlist.hxx>
23 : #include <vcl/svapp.hxx>
24 : #include <comphelper/servicehelper.hxx>
25 : #include <cppuhelper/supportsservice.hxx>
26 :
27 : #include "cursuno.hxx"
28 : #include "cellsuno.hxx"
29 : #include "docsh.hxx"
30 : #include "hints.hxx"
31 : #include "markdata.hxx"
32 : #include "dociter.hxx"
33 : #include "miscuno.hxx"
34 :
35 : using namespace com::sun::star;
36 :
37 : #define SCSHEETCELLCURSOR_SERVICE "com.sun.star.sheet.SheetCellCursor"
38 : #define SCCELLCURSOR_SERVICE "com.sun.star.table.CellCursor"
39 :
40 503 : ScCellCursorObj::ScCellCursorObj(ScDocShell* pDocSh, const ScRange& rR) :
41 503 : ScCellRangeObj( pDocSh, rR )
42 : {
43 503 : }
44 :
45 1006 : ScCellCursorObj::~ScCellCursorObj()
46 : {
47 1006 : }
48 :
49 2979 : uno::Any SAL_CALL ScCellCursorObj::queryInterface( const uno::Type& rType ) throw(uno::RuntimeException, std::exception)
50 : {
51 2979 : SC_QUERYINTERFACE( sheet::XSheetCellCursor )
52 2909 : SC_QUERYINTERFACE( sheet::XUsedAreaCursor )
53 2781 : SC_QUERYINTERFACE( table::XCellCursor )
54 :
55 2765 : return ScCellRangeObj::queryInterface( rType );
56 : }
57 :
58 7091 : void SAL_CALL ScCellCursorObj::acquire() throw()
59 : {
60 7091 : ScCellRangeObj::acquire();
61 7091 : }
62 :
63 7091 : void SAL_CALL ScCellCursorObj::release() throw()
64 : {
65 7091 : ScCellRangeObj::release();
66 7091 : }
67 :
68 0 : uno::Sequence<uno::Type> SAL_CALL ScCellCursorObj::getTypes() throw(uno::RuntimeException, std::exception)
69 : {
70 0 : static uno::Sequence<uno::Type> aTypes;
71 0 : if ( aTypes.getLength() == 0 )
72 : {
73 0 : uno::Sequence<uno::Type> aParentTypes(ScCellRangeObj::getTypes());
74 0 : long nParentLen = aParentTypes.getLength();
75 0 : const uno::Type* pParentPtr = aParentTypes.getConstArray();
76 :
77 0 : aTypes.realloc( nParentLen + 3 );
78 0 : uno::Type* pPtr = aTypes.getArray();
79 0 : pPtr[nParentLen + 0] = cppu::UnoType<sheet::XSheetCellCursor>::get();
80 0 : pPtr[nParentLen + 1] = cppu::UnoType<sheet::XUsedAreaCursor>::get();
81 0 : pPtr[nParentLen + 2] = cppu::UnoType<table::XCellCursor>::get();
82 :
83 0 : for (long i=0; i<nParentLen; i++)
84 0 : pPtr[i] = pParentPtr[i]; // parent types first
85 : }
86 0 : return aTypes;
87 : }
88 :
89 0 : uno::Sequence<sal_Int8> SAL_CALL ScCellCursorObj::getImplementationId() throw(uno::RuntimeException, std::exception)
90 : {
91 0 : return css::uno::Sequence<sal_Int8>();
92 : }
93 :
94 : // XSheetCellCursor
95 :
96 30 : void SAL_CALL ScCellCursorObj::collapseToCurrentRegion() throw(uno::RuntimeException, std::exception)
97 : {
98 30 : SolarMutexGuard aGuard;
99 30 : const ScRangeList& rRanges = GetRangeList();
100 : OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" );
101 30 : ScRange aOneRange( *rRanges[ 0 ] );
102 :
103 30 : aOneRange.Justify();
104 30 : ScDocShell* pDocSh = GetDocShell();
105 30 : if ( pDocSh )
106 : {
107 30 : SCCOL nStartCol = aOneRange.aStart.Col();
108 30 : SCROW nStartRow = aOneRange.aStart.Row();
109 30 : SCCOL nEndCol = aOneRange.aEnd.Col();
110 30 : SCROW nEndRow = aOneRange.aEnd.Row();
111 30 : SCTAB nTab = aOneRange.aStart.Tab();
112 :
113 30 : pDocSh->GetDocument().GetDataArea(
114 60 : nTab, nStartCol, nStartRow, nEndCol, nEndRow, true, false );
115 :
116 30 : ScRange aNew( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab );
117 30 : SetNewRange( aNew );
118 30 : }
119 30 : }
120 :
121 0 : void SAL_CALL ScCellCursorObj::collapseToCurrentArray()
122 : throw(uno::RuntimeException, std::exception)
123 : {
124 0 : SolarMutexGuard aGuard;
125 0 : const ScRangeList& rRanges = GetRangeList();
126 : OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" );
127 0 : ScRange aOneRange( *rRanges[ 0 ] );
128 :
129 0 : aOneRange.Justify();
130 0 : ScAddress aCursor(aOneRange.aStart); // use the start address of the range
131 :
132 0 : ScDocShell* pDocSh = GetDocShell();
133 0 : if ( pDocSh )
134 : {
135 0 : ScDocument& rDoc = pDocSh->GetDocument();
136 0 : ScRange aMatrix;
137 :
138 : // finding the matrix range is now in GetMatrixFormulaRange in the document
139 0 : if ( rDoc.GetMatrixFormulaRange( aCursor, aMatrix ) )
140 : {
141 0 : SetNewRange( aMatrix );
142 : }
143 0 : }
144 : // thats a Bug, that this assertion comes; the API Reference says, that
145 : // if there is no Matrix, the Range is left unchanged; they says nothing
146 : // about a exception
147 : /*if (!bFound)
148 : {
149 : OSL_FAIL("keine Matrix");
150 : //! Exception, oder was?
151 : }*/
152 0 : }
153 :
154 335 : void SAL_CALL ScCellCursorObj::collapseToMergedArea() throw(uno::RuntimeException, std::exception)
155 : {
156 335 : SolarMutexGuard aGuard;
157 335 : ScDocShell* pDocSh = GetDocShell();
158 335 : if ( pDocSh )
159 : {
160 335 : const ScRangeList& rRanges = GetRangeList();
161 : OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" );
162 335 : ScRange aNewRange( *rRanges[ 0 ] );
163 :
164 335 : ScDocument& rDoc = pDocSh->GetDocument();
165 335 : rDoc.ExtendOverlapped( aNewRange );
166 335 : rDoc.ExtendMerge( aNewRange ); // after ExtendOverlapped!
167 :
168 335 : SetNewRange( aNewRange );
169 335 : }
170 335 : }
171 :
172 0 : void SAL_CALL ScCellCursorObj::expandToEntireColumns() throw(uno::RuntimeException, std::exception)
173 : {
174 0 : SolarMutexGuard aGuard;
175 0 : const ScRangeList& rRanges = GetRangeList();
176 : OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" );
177 0 : ScRange aNewRange( *rRanges[ 0 ] );
178 :
179 0 : aNewRange.aStart.SetRow( 0 );
180 0 : aNewRange.aEnd.SetRow( MAXROW );
181 :
182 0 : SetNewRange( aNewRange );
183 0 : }
184 :
185 0 : void SAL_CALL ScCellCursorObj::expandToEntireRows() throw(uno::RuntimeException, std::exception)
186 : {
187 0 : SolarMutexGuard aGuard;
188 0 : const ScRangeList& rRanges = GetRangeList();
189 : OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" );
190 0 : ScRange aNewRange( *rRanges[ 0 ] );
191 :
192 0 : aNewRange.aStart.SetCol( 0 );
193 0 : aNewRange.aEnd.SetCol( MAXCOL );
194 :
195 0 : SetNewRange( aNewRange );
196 0 : }
197 :
198 19 : void SAL_CALL ScCellCursorObj::collapseToSize( sal_Int32 nColumns, sal_Int32 nRows )
199 : throw(uno::RuntimeException, std::exception)
200 : {
201 19 : SolarMutexGuard aGuard;
202 19 : if ( nColumns <= 0 || nRows <= 0 )
203 : {
204 : OSL_FAIL("leerer Range geht nicht");
205 : //! und dann?
206 : }
207 : else
208 : {
209 19 : const ScRangeList& rRanges = GetRangeList();
210 : OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" );
211 19 : ScRange aNewRange( *rRanges[ 0 ] );
212 :
213 19 : aNewRange.Justify(); //! wirklich?
214 :
215 19 : long nEndX = aNewRange.aStart.Col() + nColumns - 1;
216 19 : long nEndY = aNewRange.aStart.Row() + nRows - 1;
217 19 : if ( nEndX < 0 ) nEndX = 0;
218 19 : if ( nEndX > MAXCOL ) nEndX = MAXCOL;
219 19 : if ( nEndY < 0 ) nEndY = 0;
220 19 : if ( nEndY > MAXROW ) nEndY = MAXROW;
221 : //! Fehler/Exception oder so, wenn zu gross/zu klein?
222 :
223 19 : aNewRange.aEnd.SetCol((SCCOL)nEndX);
224 19 : aNewRange.aEnd.SetRow((SCROW)nEndY);
225 :
226 19 : aNewRange.Justify(); //! wirklich?
227 :
228 19 : SetNewRange( aNewRange );
229 19 : }
230 19 : }
231 :
232 : // XUsedAreaCursor
233 :
234 54 : void SAL_CALL ScCellCursorObj::gotoStartOfUsedArea(sal_Bool bExpand)
235 : throw(uno::RuntimeException, std::exception)
236 : {
237 54 : SolarMutexGuard aGuard;
238 54 : ScDocShell* pDocSh = GetDocShell();
239 54 : if ( pDocSh )
240 : {
241 54 : const ScRangeList& rRanges = GetRangeList();
242 : OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" );
243 54 : ScRange aNewRange( *rRanges[0] );
244 54 : SCTAB nTab = aNewRange.aStart.Tab();
245 :
246 54 : SCCOL nUsedX = 0; // Anfang holen
247 54 : SCROW nUsedY = 0;
248 54 : if (!pDocSh->GetDocument().GetDataStart( nTab, nUsedX, nUsedY ))
249 : {
250 0 : nUsedX = 0;
251 0 : nUsedY = 0;
252 : }
253 :
254 54 : aNewRange.aStart.SetCol( nUsedX );
255 54 : aNewRange.aStart.SetRow( nUsedY );
256 54 : if (!bExpand)
257 54 : aNewRange.aEnd = aNewRange.aStart;
258 54 : SetNewRange( aNewRange );
259 54 : }
260 54 : }
261 :
262 128 : void SAL_CALL ScCellCursorObj::gotoEndOfUsedArea( sal_Bool bExpand )
263 : throw(uno::RuntimeException, std::exception)
264 : {
265 128 : SolarMutexGuard aGuard;
266 128 : ScDocShell* pDocSh = GetDocShell();
267 128 : if ( pDocSh )
268 : {
269 128 : const ScRangeList& rRanges = GetRangeList();
270 : OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" );
271 128 : ScRange aNewRange( *rRanges[ 0 ]);
272 128 : SCTAB nTab = aNewRange.aStart.Tab();
273 :
274 128 : SCCOL nUsedX = 0; // Ende holen
275 128 : SCROW nUsedY = 0;
276 128 : if (!pDocSh->GetDocument().GetTableArea( nTab, nUsedX, nUsedY ))
277 : {
278 8 : nUsedX = 0;
279 8 : nUsedY = 0;
280 : }
281 :
282 128 : aNewRange.aEnd.SetCol( nUsedX );
283 128 : aNewRange.aEnd.SetRow( nUsedY );
284 128 : if (!bExpand)
285 8 : aNewRange.aStart = aNewRange.aEnd;
286 128 : SetNewRange( aNewRange );
287 128 : }
288 128 : }
289 :
290 : // XCellCursor
291 :
292 0 : void SAL_CALL ScCellCursorObj::gotoStart() throw(uno::RuntimeException, std::exception)
293 : {
294 : // this is similar to collapseToCurrentRegion
295 : //! something like gotoEdge with 4 possible directions is needed
296 :
297 0 : SolarMutexGuard aGuard;
298 0 : const ScRangeList& rRanges = GetRangeList();
299 : OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" );
300 0 : ScRange aOneRange( *rRanges[ 0 ]);
301 :
302 0 : aOneRange.Justify();
303 0 : ScDocShell* pDocSh = GetDocShell();
304 0 : if ( pDocSh )
305 : {
306 0 : SCCOL nStartCol = aOneRange.aStart.Col();
307 0 : SCROW nStartRow = aOneRange.aStart.Row();
308 0 : SCCOL nEndCol = aOneRange.aEnd.Col();
309 0 : SCROW nEndRow = aOneRange.aEnd.Row();
310 0 : SCTAB nTab = aOneRange.aStart.Tab();
311 :
312 0 : pDocSh->GetDocument().GetDataArea(
313 0 : nTab, nStartCol, nStartRow, nEndCol, nEndRow, false, false );
314 :
315 0 : ScRange aNew( nStartCol, nStartRow, nTab );
316 0 : SetNewRange( aNew );
317 0 : }
318 0 : }
319 :
320 16 : void SAL_CALL ScCellCursorObj::gotoEnd() throw(uno::RuntimeException, std::exception)
321 : {
322 : // this is similar to collapseToCurrentRegion
323 : //! something like gotoEdge with 4 possible directions is needed
324 :
325 16 : SolarMutexGuard aGuard;
326 16 : const ScRangeList& rRanges = GetRangeList();
327 : OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" );
328 16 : ScRange aOneRange( *rRanges[ 0 ] );
329 :
330 16 : aOneRange.Justify();
331 16 : ScDocShell* pDocSh = GetDocShell();
332 16 : if ( pDocSh )
333 : {
334 16 : SCCOL nStartCol = aOneRange.aStart.Col();
335 16 : SCROW nStartRow = aOneRange.aStart.Row();
336 16 : SCCOL nEndCol = aOneRange.aEnd.Col();
337 16 : SCROW nEndRow = aOneRange.aEnd.Row();
338 16 : SCTAB nTab = aOneRange.aStart.Tab();
339 :
340 16 : pDocSh->GetDocument().GetDataArea(
341 32 : nTab, nStartCol, nStartRow, nEndCol, nEndRow, false, false );
342 :
343 16 : ScRange aNew( nEndCol, nEndRow, nTab );
344 16 : SetNewRange( aNew );
345 16 : }
346 16 : }
347 :
348 0 : void SAL_CALL ScCellCursorObj::gotoNext() throw(uno::RuntimeException, std::exception)
349 : {
350 0 : SolarMutexGuard aGuard;
351 0 : const ScRangeList& rRanges = GetRangeList();
352 : OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" );
353 0 : ScRange aOneRange( *rRanges[ 0 ] );
354 :
355 0 : aOneRange.Justify();
356 0 : ScAddress aCursor(aOneRange.aStart); // bei Block immer den Start nehmen
357 :
358 0 : ScMarkData aMark; // not used with bMarked=FALSE
359 0 : SCCOL nNewX = aCursor.Col();
360 0 : SCROW nNewY = aCursor.Row();
361 0 : SCTAB nTab = aCursor.Tab();
362 0 : ScDocShell* pDocSh = GetDocShell();
363 0 : if ( pDocSh )
364 0 : pDocSh->GetDocument().GetNextPos( nNewX,nNewY, nTab, 1,0, false,true, aMark );
365 : //! sonst Exception oder so
366 :
367 0 : SetNewRange( ScRange( nNewX, nNewY, nTab ) );
368 0 : }
369 :
370 0 : void SAL_CALL ScCellCursorObj::gotoPrevious() throw(uno::RuntimeException, std::exception)
371 : {
372 0 : SolarMutexGuard aGuard;
373 0 : const ScRangeList& rRanges = GetRangeList();
374 : OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" );
375 0 : ScRange aOneRange( *rRanges[ 0 ] );
376 :
377 0 : aOneRange.Justify();
378 0 : ScAddress aCursor(aOneRange.aStart); // bei Block immer den Start nehmen
379 :
380 0 : ScMarkData aMark; // not used with bMarked=FALSE
381 0 : SCCOL nNewX = aCursor.Col();
382 0 : SCROW nNewY = aCursor.Row();
383 0 : SCTAB nTab = aCursor.Tab();
384 0 : ScDocShell* pDocSh = GetDocShell();
385 0 : if ( pDocSh )
386 0 : pDocSh->GetDocument().GetNextPos( nNewX,nNewY, nTab, -1,0, false,true, aMark );
387 : //! sonst Exception oder so
388 :
389 0 : SetNewRange( ScRange( nNewX, nNewY, nTab ) );
390 0 : }
391 :
392 0 : void SAL_CALL ScCellCursorObj::gotoOffset( sal_Int32 nColumnOffset, sal_Int32 nRowOffset )
393 : throw(uno::RuntimeException, std::exception)
394 : {
395 0 : SolarMutexGuard aGuard;
396 0 : const ScRangeList& rRanges = GetRangeList();
397 : OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" );
398 0 : ScRange aOneRange( *rRanges[ 0 ] );
399 0 : aOneRange.Justify();
400 :
401 0 : if ( aOneRange.aStart.Col() + nColumnOffset >= 0 &&
402 0 : aOneRange.aEnd.Col() + nColumnOffset <= MAXCOL &&
403 0 : aOneRange.aStart.Row() + nRowOffset >= 0 &&
404 0 : aOneRange.aEnd.Row() + nRowOffset <= MAXROW )
405 : {
406 0 : ScRange aNew( (SCCOL)(aOneRange.aStart.Col() + nColumnOffset),
407 0 : (SCROW)(aOneRange.aStart.Row() + nRowOffset),
408 0 : aOneRange.aStart.Tab(),
409 0 : (SCCOL)(aOneRange.aEnd.Col() + nColumnOffset),
410 0 : (SCROW)(aOneRange.aEnd.Row() + nRowOffset),
411 0 : aOneRange.aEnd.Tab() );
412 0 : SetNewRange( aNew );
413 0 : }
414 0 : }
415 :
416 : // XSheetCellRange
417 :
418 1 : uno::Reference<sheet::XSpreadsheet> SAL_CALL ScCellCursorObj::getSpreadsheet()
419 : throw(uno::RuntimeException, std::exception)
420 : {
421 1 : SolarMutexGuard aGuard;
422 1 : return ScCellRangeObj::getSpreadsheet();
423 : }
424 :
425 : // XCellRange
426 :
427 60 : uno::Reference<table::XCell> SAL_CALL ScCellCursorObj::getCellByPosition(
428 : sal_Int32 nColumn, sal_Int32 nRow )
429 : throw(lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
430 : {
431 60 : SolarMutexGuard aGuard;
432 60 : return ScCellRangeObj::getCellByPosition(nColumn,nRow);
433 : }
434 :
435 0 : uno::Reference<table::XCellRange> SAL_CALL ScCellCursorObj::getCellRangeByPosition(
436 : sal_Int32 nLeft, sal_Int32 nTop, sal_Int32 nRight, sal_Int32 nBottom )
437 : throw(lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
438 : {
439 0 : SolarMutexGuard aGuard;
440 0 : return ScCellRangeObj::getCellRangeByPosition(nLeft,nTop,nRight,nBottom);
441 : }
442 :
443 0 : uno::Reference<table::XCellRange> SAL_CALL ScCellCursorObj::getCellRangeByName(
444 : const OUString& rRange ) throw(uno::RuntimeException, std::exception)
445 : {
446 0 : SolarMutexGuard aGuard;
447 0 : return ScCellRangeObj::getCellRangeByName(rRange);
448 : }
449 :
450 : // XServiceInfo
451 :
452 0 : OUString SAL_CALL ScCellCursorObj::getImplementationName() throw(uno::RuntimeException, std::exception)
453 : {
454 0 : return OUString( "ScCellCursorObj" );
455 : }
456 :
457 0 : sal_Bool SAL_CALL ScCellCursorObj::supportsService( const OUString& rServiceName )
458 : throw(uno::RuntimeException, std::exception)
459 : {
460 0 : return cppu::supportsService(this, rServiceName);
461 : }
462 :
463 0 : uno::Sequence<OUString> SAL_CALL ScCellCursorObj::getSupportedServiceNames()
464 : throw(uno::RuntimeException, std::exception)
465 : {
466 : // get all service names from cell range
467 0 : uno::Sequence<OUString> aParentSeq(ScCellRangeObj::getSupportedServiceNames());
468 0 : sal_Int32 nParentLen = aParentSeq.getLength();
469 0 : const OUString* pParentArr = aParentSeq.getConstArray();
470 :
471 : // SheetCellCursor should be first (?)
472 0 : uno::Sequence<OUString> aTotalSeq( nParentLen + 2 );
473 0 : OUString* pTotalArr = aTotalSeq.getArray();
474 0 : pTotalArr[0] = SCSHEETCELLCURSOR_SERVICE;
475 0 : pTotalArr[1] = SCCELLCURSOR_SERVICE;
476 :
477 : // append cell range services
478 0 : for (long i=0; i<nParentLen; i++)
479 0 : pTotalArr[i+2] = pParentArr[i];
480 :
481 0 : return aTotalSeq;
482 156 : }
483 :
484 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|