1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
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>
27 #include "cursuno.hxx"
28 #include "cellsuno.hxx"
31 #include "markdata.hxx"
32 #include "dociter.hxx"
33 #include "miscuno.hxx"
35 using namespace com::sun::star
;
37 #define SCSHEETCELLCURSOR_SERVICE "com.sun.star.sheet.SheetCellCursor"
38 #define SCCELLCURSOR_SERVICE "com.sun.star.table.CellCursor"
40 ScCellCursorObj::ScCellCursorObj(ScDocShell
* pDocSh
, const ScRange
& rR
) :
41 ScCellRangeObj( pDocSh
, rR
)
45 ScCellCursorObj::~ScCellCursorObj()
49 uno::Any SAL_CALL
ScCellCursorObj::queryInterface( const uno::Type
& rType
) throw(uno::RuntimeException
, std::exception
)
51 SC_QUERYINTERFACE( sheet::XSheetCellCursor
)
52 SC_QUERYINTERFACE( sheet::XUsedAreaCursor
)
53 SC_QUERYINTERFACE( table::XCellCursor
)
55 return ScCellRangeObj::queryInterface( rType
);
58 void SAL_CALL
ScCellCursorObj::acquire() throw()
60 ScCellRangeObj::acquire();
63 void SAL_CALL
ScCellCursorObj::release() throw()
65 ScCellRangeObj::release();
68 uno::Sequence
<uno::Type
> SAL_CALL
ScCellCursorObj::getTypes() throw(uno::RuntimeException
, std::exception
)
70 static uno::Sequence
<uno::Type
> aTypes
;
71 if ( aTypes
.getLength() == 0 )
73 uno::Sequence
<uno::Type
> aParentTypes(ScCellRangeObj::getTypes());
74 long nParentLen
= aParentTypes
.getLength();
75 const uno::Type
* pParentPtr
= aParentTypes
.getConstArray();
77 aTypes
.realloc( nParentLen
+ 3 );
78 uno::Type
* pPtr
= aTypes
.getArray();
79 pPtr
[nParentLen
+ 0] = cppu::UnoType
<sheet::XSheetCellCursor
>::get();
80 pPtr
[nParentLen
+ 1] = cppu::UnoType
<sheet::XUsedAreaCursor
>::get();
81 pPtr
[nParentLen
+ 2] = cppu::UnoType
<table::XCellCursor
>::get();
83 for (long i
=0; i
<nParentLen
; i
++)
84 pPtr
[i
] = pParentPtr
[i
]; // parent types first
89 uno::Sequence
<sal_Int8
> SAL_CALL
ScCellCursorObj::getImplementationId() throw(uno::RuntimeException
, std::exception
)
91 return css::uno::Sequence
<sal_Int8
>();
96 void SAL_CALL
ScCellCursorObj::collapseToCurrentRegion() throw(uno::RuntimeException
, std::exception
)
98 SolarMutexGuard aGuard
;
99 const ScRangeList
& rRanges
= GetRangeList();
100 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
101 ScRange
aOneRange( *rRanges
[ 0 ] );
104 ScDocShell
* pDocSh
= GetDocShell();
107 SCCOL nStartCol
= aOneRange
.aStart
.Col();
108 SCROW nStartRow
= aOneRange
.aStart
.Row();
109 SCCOL nEndCol
= aOneRange
.aEnd
.Col();
110 SCROW nEndRow
= aOneRange
.aEnd
.Row();
111 SCTAB nTab
= aOneRange
.aStart
.Tab();
113 pDocSh
->GetDocument().GetDataArea(
114 nTab
, nStartCol
, nStartRow
, nEndCol
, nEndRow
, true, false );
116 ScRange
aNew( nStartCol
, nStartRow
, nTab
, nEndCol
, nEndRow
, nTab
);
121 void SAL_CALL
ScCellCursorObj::collapseToCurrentArray()
122 throw(uno::RuntimeException
, std::exception
)
124 SolarMutexGuard aGuard
;
125 const ScRangeList
& rRanges
= GetRangeList();
126 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
127 ScRange
aOneRange( *rRanges
[ 0 ] );
130 ScAddress
aCursor(aOneRange
.aStart
); // use the start address of the range
132 ScDocShell
* pDocSh
= GetDocShell();
135 ScDocument
& rDoc
= pDocSh
->GetDocument();
138 // finding the matrix range is now in GetMatrixFormulaRange in the document
139 if ( rDoc
.GetMatrixFormulaRange( aCursor
, aMatrix
) )
141 SetNewRange( aMatrix
);
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
149 OSL_FAIL("keine Matrix");
150 //! Exception, oder was?
154 void SAL_CALL
ScCellCursorObj::collapseToMergedArea() throw(uno::RuntimeException
, std::exception
)
156 SolarMutexGuard aGuard
;
157 ScDocShell
* pDocSh
= GetDocShell();
160 const ScRangeList
& rRanges
= GetRangeList();
161 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
162 ScRange
aNewRange( *rRanges
[ 0 ] );
164 ScDocument
& rDoc
= pDocSh
->GetDocument();
165 rDoc
.ExtendOverlapped( aNewRange
);
166 rDoc
.ExtendMerge( aNewRange
); // after ExtendOverlapped!
168 SetNewRange( aNewRange
);
172 void SAL_CALL
ScCellCursorObj::expandToEntireColumns() throw(uno::RuntimeException
, std::exception
)
174 SolarMutexGuard aGuard
;
175 const ScRangeList
& rRanges
= GetRangeList();
176 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
177 ScRange
aNewRange( *rRanges
[ 0 ] );
179 aNewRange
.aStart
.SetRow( 0 );
180 aNewRange
.aEnd
.SetRow( MAXROW
);
182 SetNewRange( aNewRange
);
185 void SAL_CALL
ScCellCursorObj::expandToEntireRows() throw(uno::RuntimeException
, std::exception
)
187 SolarMutexGuard aGuard
;
188 const ScRangeList
& rRanges
= GetRangeList();
189 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
190 ScRange
aNewRange( *rRanges
[ 0 ] );
192 aNewRange
.aStart
.SetCol( 0 );
193 aNewRange
.aEnd
.SetCol( MAXCOL
);
195 SetNewRange( aNewRange
);
198 void SAL_CALL
ScCellCursorObj::collapseToSize( sal_Int32 nColumns
, sal_Int32 nRows
)
199 throw(uno::RuntimeException
, std::exception
)
201 SolarMutexGuard aGuard
;
202 if ( nColumns
<= 0 || nRows
<= 0 )
204 OSL_FAIL("leerer Range geht nicht");
209 const ScRangeList
& rRanges
= GetRangeList();
210 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
211 ScRange
aNewRange( *rRanges
[ 0 ] );
213 aNewRange
.Justify(); //! wirklich?
215 long nEndX
= aNewRange
.aStart
.Col() + nColumns
- 1;
216 long nEndY
= aNewRange
.aStart
.Row() + nRows
- 1;
217 if ( nEndX
< 0 ) nEndX
= 0;
218 if ( nEndX
> MAXCOL
) nEndX
= MAXCOL
;
219 if ( nEndY
< 0 ) nEndY
= 0;
220 if ( nEndY
> MAXROW
) nEndY
= MAXROW
;
221 //! Fehler/Exception oder so, wenn zu gross/zu klein?
223 aNewRange
.aEnd
.SetCol((SCCOL
)nEndX
);
224 aNewRange
.aEnd
.SetRow((SCROW
)nEndY
);
226 aNewRange
.Justify(); //! wirklich?
228 SetNewRange( aNewRange
);
234 void SAL_CALL
ScCellCursorObj::gotoStartOfUsedArea(sal_Bool bExpand
)
235 throw(uno::RuntimeException
, std::exception
)
237 SolarMutexGuard aGuard
;
238 ScDocShell
* pDocSh
= GetDocShell();
241 const ScRangeList
& rRanges
= GetRangeList();
242 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
243 ScRange
aNewRange( *rRanges
[0] );
244 SCTAB nTab
= aNewRange
.aStart
.Tab();
246 SCCOL nUsedX
= 0; // Anfang holen
248 if (!pDocSh
->GetDocument().GetDataStart( nTab
, nUsedX
, nUsedY
))
254 aNewRange
.aStart
.SetCol( nUsedX
);
255 aNewRange
.aStart
.SetRow( nUsedY
);
257 aNewRange
.aEnd
= aNewRange
.aStart
;
258 SetNewRange( aNewRange
);
262 void SAL_CALL
ScCellCursorObj::gotoEndOfUsedArea( sal_Bool bExpand
)
263 throw(uno::RuntimeException
, std::exception
)
265 SolarMutexGuard aGuard
;
266 ScDocShell
* pDocSh
= GetDocShell();
269 const ScRangeList
& rRanges
= GetRangeList();
270 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
271 ScRange
aNewRange( *rRanges
[ 0 ]);
272 SCTAB nTab
= aNewRange
.aStart
.Tab();
274 SCCOL nUsedX
= 0; // Ende holen
276 if (!pDocSh
->GetDocument().GetTableArea( nTab
, nUsedX
, nUsedY
))
282 aNewRange
.aEnd
.SetCol( nUsedX
);
283 aNewRange
.aEnd
.SetRow( nUsedY
);
285 aNewRange
.aStart
= aNewRange
.aEnd
;
286 SetNewRange( aNewRange
);
292 void SAL_CALL
ScCellCursorObj::gotoStart() throw(uno::RuntimeException
, std::exception
)
294 // this is similar to collapseToCurrentRegion
295 //! something like gotoEdge with 4 possible directions is needed
297 SolarMutexGuard aGuard
;
298 const ScRangeList
& rRanges
= GetRangeList();
299 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
300 ScRange
aOneRange( *rRanges
[ 0 ]);
303 ScDocShell
* pDocSh
= GetDocShell();
306 SCCOL nStartCol
= aOneRange
.aStart
.Col();
307 SCROW nStartRow
= aOneRange
.aStart
.Row();
308 SCCOL nEndCol
= aOneRange
.aEnd
.Col();
309 SCROW nEndRow
= aOneRange
.aEnd
.Row();
310 SCTAB nTab
= aOneRange
.aStart
.Tab();
312 pDocSh
->GetDocument().GetDataArea(
313 nTab
, nStartCol
, nStartRow
, nEndCol
, nEndRow
, false, false );
315 ScRange
aNew( nStartCol
, nStartRow
, nTab
);
320 void SAL_CALL
ScCellCursorObj::gotoEnd() throw(uno::RuntimeException
, std::exception
)
322 // this is similar to collapseToCurrentRegion
323 //! something like gotoEdge with 4 possible directions is needed
325 SolarMutexGuard aGuard
;
326 const ScRangeList
& rRanges
= GetRangeList();
327 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
328 ScRange
aOneRange( *rRanges
[ 0 ] );
331 ScDocShell
* pDocSh
= GetDocShell();
334 SCCOL nStartCol
= aOneRange
.aStart
.Col();
335 SCROW nStartRow
= aOneRange
.aStart
.Row();
336 SCCOL nEndCol
= aOneRange
.aEnd
.Col();
337 SCROW nEndRow
= aOneRange
.aEnd
.Row();
338 SCTAB nTab
= aOneRange
.aStart
.Tab();
340 pDocSh
->GetDocument().GetDataArea(
341 nTab
, nStartCol
, nStartRow
, nEndCol
, nEndRow
, false, false );
343 ScRange
aNew( nEndCol
, nEndRow
, nTab
);
348 void SAL_CALL
ScCellCursorObj::gotoNext() throw(uno::RuntimeException
, std::exception
)
350 SolarMutexGuard aGuard
;
351 const ScRangeList
& rRanges
= GetRangeList();
352 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
353 ScRange
aOneRange( *rRanges
[ 0 ] );
356 ScAddress
aCursor(aOneRange
.aStart
); // bei Block immer den Start nehmen
358 ScMarkData aMark
; // not used with bMarked=FALSE
359 SCCOL nNewX
= aCursor
.Col();
360 SCROW nNewY
= aCursor
.Row();
361 SCTAB nTab
= aCursor
.Tab();
362 ScDocShell
* pDocSh
= GetDocShell();
364 pDocSh
->GetDocument().GetNextPos( nNewX
,nNewY
, nTab
, 1,0, false,true, aMark
);
365 //! sonst Exception oder so
367 SetNewRange( ScRange( nNewX
, nNewY
, nTab
) );
370 void SAL_CALL
ScCellCursorObj::gotoPrevious() throw(uno::RuntimeException
, std::exception
)
372 SolarMutexGuard aGuard
;
373 const ScRangeList
& rRanges
= GetRangeList();
374 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
375 ScRange
aOneRange( *rRanges
[ 0 ] );
378 ScAddress
aCursor(aOneRange
.aStart
); // bei Block immer den Start nehmen
380 ScMarkData aMark
; // not used with bMarked=FALSE
381 SCCOL nNewX
= aCursor
.Col();
382 SCROW nNewY
= aCursor
.Row();
383 SCTAB nTab
= aCursor
.Tab();
384 ScDocShell
* pDocSh
= GetDocShell();
386 pDocSh
->GetDocument().GetNextPos( nNewX
,nNewY
, nTab
, -1,0, false,true, aMark
);
387 //! sonst Exception oder so
389 SetNewRange( ScRange( nNewX
, nNewY
, nTab
) );
392 void SAL_CALL
ScCellCursorObj::gotoOffset( sal_Int32 nColumnOffset
, sal_Int32 nRowOffset
)
393 throw(uno::RuntimeException
, std::exception
)
395 SolarMutexGuard aGuard
;
396 const ScRangeList
& rRanges
= GetRangeList();
397 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
398 ScRange
aOneRange( *rRanges
[ 0 ] );
401 if ( aOneRange
.aStart
.Col() + nColumnOffset
>= 0 &&
402 aOneRange
.aEnd
.Col() + nColumnOffset
<= MAXCOL
&&
403 aOneRange
.aStart
.Row() + nRowOffset
>= 0 &&
404 aOneRange
.aEnd
.Row() + nRowOffset
<= MAXROW
)
406 ScRange
aNew( (SCCOL
)(aOneRange
.aStart
.Col() + nColumnOffset
),
407 (SCROW
)(aOneRange
.aStart
.Row() + nRowOffset
),
408 aOneRange
.aStart
.Tab(),
409 (SCCOL
)(aOneRange
.aEnd
.Col() + nColumnOffset
),
410 (SCROW
)(aOneRange
.aEnd
.Row() + nRowOffset
),
411 aOneRange
.aEnd
.Tab() );
418 uno::Reference
<sheet::XSpreadsheet
> SAL_CALL
ScCellCursorObj::getSpreadsheet()
419 throw(uno::RuntimeException
, std::exception
)
421 SolarMutexGuard aGuard
;
422 return ScCellRangeObj::getSpreadsheet();
427 uno::Reference
<table::XCell
> SAL_CALL
ScCellCursorObj::getCellByPosition(
428 sal_Int32 nColumn
, sal_Int32 nRow
)
429 throw(lang::IndexOutOfBoundsException
, uno::RuntimeException
, std::exception
)
431 SolarMutexGuard aGuard
;
432 return ScCellRangeObj::getCellByPosition(nColumn
,nRow
);
435 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
)
439 SolarMutexGuard aGuard
;
440 return ScCellRangeObj::getCellRangeByPosition(nLeft
,nTop
,nRight
,nBottom
);
443 uno::Reference
<table::XCellRange
> SAL_CALL
ScCellCursorObj::getCellRangeByName(
444 const OUString
& rRange
) throw(uno::RuntimeException
, std::exception
)
446 SolarMutexGuard aGuard
;
447 return ScCellRangeObj::getCellRangeByName(rRange
);
452 OUString SAL_CALL
ScCellCursorObj::getImplementationName() throw(uno::RuntimeException
, std::exception
)
454 return OUString( "ScCellCursorObj" );
457 sal_Bool SAL_CALL
ScCellCursorObj::supportsService( const OUString
& rServiceName
)
458 throw(uno::RuntimeException
, std::exception
)
460 return cppu::supportsService(this, rServiceName
);
463 uno::Sequence
<OUString
> SAL_CALL
ScCellCursorObj::getSupportedServiceNames()
464 throw(uno::RuntimeException
, std::exception
)
466 // get all service names from cell range
467 uno::Sequence
<OUString
> aParentSeq(ScCellRangeObj::getSupportedServiceNames());
468 sal_Int32 nParentLen
= aParentSeq
.getLength();
469 const OUString
* pParentArr
= aParentSeq
.getConstArray();
471 // SheetCellCursor should be first (?)
472 uno::Sequence
<OUString
> aTotalSeq( nParentLen
+ 2 );
473 OUString
* pTotalArr
= aTotalSeq
.getArray();
474 pTotalArr
[0] = SCSHEETCELLCURSOR_SERVICE
;
475 pTotalArr
[1] = SCCELLCURSOR_SERVICE
;
477 // append cell range services
478 for (long i
=0; i
<nParentLen
; i
++)
479 pTotalArr
[i
+2] = pParentArr
[i
];
484 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */