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