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>
26 #include "cursuno.hxx"
27 #include "cellsuno.hxx"
30 #include "markdata.hxx"
31 #include "dociter.hxx"
32 #include "miscuno.hxx"
34 using namespace com::sun::star
;
36 //------------------------------------------------------------------------
38 #define SCSHEETCELLCURSOR_SERVICE "com.sun.star.sheet.SheetCellCursor"
39 #define SCCELLCURSOR_SERVICE "com.sun.star.table.CellCursor"
41 //------------------------------------------------------------------------
43 ScCellCursorObj::ScCellCursorObj(ScDocShell
* pDocSh
, const ScRange
& rR
) :
44 ScCellRangeObj( pDocSh
, rR
)
48 ScCellCursorObj::~ScCellCursorObj()
52 uno::Any SAL_CALL
ScCellCursorObj::queryInterface( const uno::Type
& rType
) throw(uno::RuntimeException
)
54 SC_QUERYINTERFACE( sheet::XSheetCellCursor
)
55 SC_QUERYINTERFACE( sheet::XUsedAreaCursor
)
56 SC_QUERYINTERFACE( table::XCellCursor
)
58 return ScCellRangeObj::queryInterface( rType
);
61 void SAL_CALL
ScCellCursorObj::acquire() throw()
63 ScCellRangeObj::acquire();
66 void SAL_CALL
ScCellCursorObj::release() throw()
68 ScCellRangeObj::release();
71 uno::Sequence
<uno::Type
> SAL_CALL
ScCellCursorObj::getTypes() throw(uno::RuntimeException
)
73 static uno::Sequence
<uno::Type
> aTypes
;
74 if ( aTypes
.getLength() == 0 )
76 uno::Sequence
<uno::Type
> aParentTypes(ScCellRangeObj::getTypes());
77 long nParentLen
= aParentTypes
.getLength();
78 const uno::Type
* pParentPtr
= aParentTypes
.getConstArray();
80 aTypes
.realloc( nParentLen
+ 3 );
81 uno::Type
* pPtr
= aTypes
.getArray();
82 pPtr
[nParentLen
+ 0] = getCppuType((const uno::Reference
<sheet::XSheetCellCursor
>*)0);
83 pPtr
[nParentLen
+ 1] = getCppuType((const uno::Reference
<sheet::XUsedAreaCursor
>*)0);
84 pPtr
[nParentLen
+ 2] = getCppuType((const uno::Reference
<table::XCellCursor
>*)0);
86 for (long i
=0; i
<nParentLen
; i
++)
87 pPtr
[i
] = pParentPtr
[i
]; // parent types first
94 class theScCellCursorObjImplementationId
: public rtl::Static
< UnoTunnelIdInit
, theScCellCursorObjImplementationId
> {};
97 uno::Sequence
<sal_Int8
> SAL_CALL
ScCellCursorObj::getImplementationId() throw(uno::RuntimeException
)
99 return theScCellCursorObjImplementationId::get().getSeq();
104 void SAL_CALL
ScCellCursorObj::collapseToCurrentRegion() throw(uno::RuntimeException
)
106 SolarMutexGuard aGuard
;
107 const ScRangeList
& rRanges
= GetRangeList();
108 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
109 ScRange
aOneRange( *rRanges
[ 0 ] );
112 ScDocShell
* pDocSh
= GetDocShell();
115 SCCOL nStartCol
= aOneRange
.aStart
.Col();
116 SCROW nStartRow
= aOneRange
.aStart
.Row();
117 SCCOL nEndCol
= aOneRange
.aEnd
.Col();
118 SCROW nEndRow
= aOneRange
.aEnd
.Row();
119 SCTAB nTab
= aOneRange
.aStart
.Tab();
121 pDocSh
->GetDocument()->GetDataArea(
122 nTab
, nStartCol
, nStartRow
, nEndCol
, nEndRow
, true, false );
124 ScRange
aNew( nStartCol
, nStartRow
, nTab
, nEndCol
, nEndRow
, nTab
);
129 void SAL_CALL
ScCellCursorObj::collapseToCurrentArray() throw(uno::RuntimeException
)
131 SolarMutexGuard aGuard
;
132 const ScRangeList
& rRanges
= GetRangeList();
133 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
134 ScRange
aOneRange( *rRanges
[ 0 ] );
137 ScAddress
aCursor(aOneRange
.aStart
); // use the start address of the range
139 ScDocShell
* pDocSh
= GetDocShell();
142 ScDocument
* pDoc
= pDocSh
->GetDocument();
145 // finding the matrix range is now in GetMatrixFormulaRange in the document
146 if ( pDoc
->GetMatrixFormulaRange( aCursor
, aMatrix
) )
148 SetNewRange( aMatrix
);
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
156 OSL_FAIL("keine Matrix");
157 //! Exception, oder was?
161 void SAL_CALL
ScCellCursorObj::collapseToMergedArea() throw(uno::RuntimeException
)
163 SolarMutexGuard aGuard
;
164 ScDocShell
* pDocSh
= GetDocShell();
167 const ScRangeList
& rRanges
= GetRangeList();
168 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
169 ScRange
aNewRange( *rRanges
[ 0 ] );
171 ScDocument
* pDoc
= pDocSh
->GetDocument();
172 pDoc
->ExtendOverlapped( aNewRange
);
173 pDoc
->ExtendMerge( aNewRange
); // after ExtendOverlapped!
175 SetNewRange( aNewRange
);
179 void SAL_CALL
ScCellCursorObj::expandToEntireColumns() throw(uno::RuntimeException
)
181 SolarMutexGuard aGuard
;
182 const ScRangeList
& rRanges
= GetRangeList();
183 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
184 ScRange
aNewRange( *rRanges
[ 0 ] );
186 aNewRange
.aStart
.SetRow( 0 );
187 aNewRange
.aEnd
.SetRow( MAXROW
);
189 SetNewRange( aNewRange
);
192 void SAL_CALL
ScCellCursorObj::expandToEntireRows() throw(uno::RuntimeException
)
194 SolarMutexGuard aGuard
;
195 const ScRangeList
& rRanges
= GetRangeList();
196 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
197 ScRange
aNewRange( *rRanges
[ 0 ] );
199 aNewRange
.aStart
.SetCol( 0 );
200 aNewRange
.aEnd
.SetCol( MAXCOL
);
202 SetNewRange( aNewRange
);
205 void SAL_CALL
ScCellCursorObj::collapseToSize( sal_Int32 nColumns
, sal_Int32 nRows
)
206 throw(uno::RuntimeException
)
208 SolarMutexGuard aGuard
;
209 if ( nColumns
<= 0 || nRows
<= 0 )
211 OSL_FAIL("leerer Range geht nicht");
216 const ScRangeList
& rRanges
= GetRangeList();
217 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
218 ScRange
aNewRange( *rRanges
[ 0 ] );
220 aNewRange
.Justify(); //! wirklich?
222 long nEndX
= aNewRange
.aStart
.Col() + nColumns
- 1;
223 long nEndY
= aNewRange
.aStart
.Row() + nRows
- 1;
224 if ( nEndX
< 0 ) nEndX
= 0;
225 if ( nEndX
> MAXCOL
) nEndX
= MAXCOL
;
226 if ( nEndY
< 0 ) nEndY
= 0;
227 if ( nEndY
> MAXROW
) nEndY
= MAXROW
;
228 //! Fehler/Exception oder so, wenn zu gross/zu klein?
230 aNewRange
.aEnd
.SetCol((SCCOL
)nEndX
);
231 aNewRange
.aEnd
.SetRow((SCROW
)nEndY
);
233 aNewRange
.Justify(); //! wirklich?
235 SetNewRange( aNewRange
);
241 void SAL_CALL
ScCellCursorObj::gotoStartOfUsedArea( sal_Bool bExpand
)
242 throw(uno::RuntimeException
)
244 SolarMutexGuard aGuard
;
245 ScDocShell
* pDocSh
= GetDocShell();
248 const ScRangeList
& rRanges
= GetRangeList();
249 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
250 ScRange
aNewRange( *rRanges
[0] );
251 SCTAB nTab
= aNewRange
.aStart
.Tab();
253 SCCOL nUsedX
= 0; // Anfang holen
255 if (!pDocSh
->GetDocument()->GetDataStart( nTab
, nUsedX
, nUsedY
))
261 aNewRange
.aStart
.SetCol( nUsedX
);
262 aNewRange
.aStart
.SetRow( nUsedY
);
264 aNewRange
.aEnd
= aNewRange
.aStart
;
265 SetNewRange( aNewRange
);
269 void SAL_CALL
ScCellCursorObj::gotoEndOfUsedArea( sal_Bool bExpand
)
270 throw(uno::RuntimeException
)
272 SolarMutexGuard aGuard
;
273 ScDocShell
* pDocSh
= GetDocShell();
276 const ScRangeList
& rRanges
= GetRangeList();
277 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
278 ScRange
aNewRange( *rRanges
[ 0 ]);
279 SCTAB nTab
= aNewRange
.aStart
.Tab();
281 SCCOL nUsedX
= 0; // Ende holen
283 if (!pDocSh
->GetDocument()->GetTableArea( nTab
, nUsedX
, nUsedY
))
289 aNewRange
.aEnd
.SetCol( nUsedX
);
290 aNewRange
.aEnd
.SetRow( nUsedY
);
292 aNewRange
.aStart
= aNewRange
.aEnd
;
293 SetNewRange( aNewRange
);
299 void SAL_CALL
ScCellCursorObj::gotoStart() throw(uno::RuntimeException
)
301 // this is similar to collapseToCurrentRegion
302 //! something like gotoEdge with 4 possible directions is needed
304 SolarMutexGuard aGuard
;
305 const ScRangeList
& rRanges
= GetRangeList();
306 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
307 ScRange
aOneRange( *rRanges
[ 0 ]);
310 ScDocShell
* pDocSh
= GetDocShell();
313 SCCOL nStartCol
= aOneRange
.aStart
.Col();
314 SCROW nStartRow
= aOneRange
.aStart
.Row();
315 SCCOL nEndCol
= aOneRange
.aEnd
.Col();
316 SCROW nEndRow
= aOneRange
.aEnd
.Row();
317 SCTAB nTab
= aOneRange
.aStart
.Tab();
319 pDocSh
->GetDocument()->GetDataArea(
320 nTab
, nStartCol
, nStartRow
, nEndCol
, nEndRow
, false, false );
322 ScRange
aNew( nStartCol
, nStartRow
, nTab
);
327 void SAL_CALL
ScCellCursorObj::gotoEnd() throw(uno::RuntimeException
)
329 // this is similar to collapseToCurrentRegion
330 //! something like gotoEdge with 4 possible directions is needed
332 SolarMutexGuard aGuard
;
333 const ScRangeList
& rRanges
= GetRangeList();
334 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
335 ScRange
aOneRange( *rRanges
[ 0 ] );
338 ScDocShell
* pDocSh
= GetDocShell();
341 SCCOL nStartCol
= aOneRange
.aStart
.Col();
342 SCROW nStartRow
= aOneRange
.aStart
.Row();
343 SCCOL nEndCol
= aOneRange
.aEnd
.Col();
344 SCROW nEndRow
= aOneRange
.aEnd
.Row();
345 SCTAB nTab
= aOneRange
.aStart
.Tab();
347 pDocSh
->GetDocument()->GetDataArea(
348 nTab
, nStartCol
, nStartRow
, nEndCol
, nEndRow
, false, false );
350 ScRange
aNew( nEndCol
, nEndRow
, nTab
);
355 void SAL_CALL
ScCellCursorObj::gotoNext() throw(uno::RuntimeException
)
357 SolarMutexGuard aGuard
;
358 const ScRangeList
& rRanges
= GetRangeList();
359 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
360 ScRange
aOneRange( *rRanges
[ 0 ] );
363 ScAddress
aCursor(aOneRange
.aStart
); // bei Block immer den Start nehmen
365 ScMarkData aMark
; // not used with bMarked=FALSE
366 SCCOL nNewX
= aCursor
.Col();
367 SCROW nNewY
= aCursor
.Row();
368 SCTAB nTab
= aCursor
.Tab();
369 ScDocShell
* pDocSh
= GetDocShell();
371 pDocSh
->GetDocument()->GetNextPos( nNewX
,nNewY
, nTab
, 1,0, false,sal_True
, aMark
);
372 //! sonst Exception oder so
374 SetNewRange( ScRange( nNewX
, nNewY
, nTab
) );
377 void SAL_CALL
ScCellCursorObj::gotoPrevious() throw(uno::RuntimeException
)
379 SolarMutexGuard aGuard
;
380 const ScRangeList
& rRanges
= GetRangeList();
381 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
382 ScRange
aOneRange( *rRanges
[ 0 ] );
385 ScAddress
aCursor(aOneRange
.aStart
); // bei Block immer den Start nehmen
387 ScMarkData aMark
; // not used with bMarked=FALSE
388 SCCOL nNewX
= aCursor
.Col();
389 SCROW nNewY
= aCursor
.Row();
390 SCTAB nTab
= aCursor
.Tab();
391 ScDocShell
* pDocSh
= GetDocShell();
393 pDocSh
->GetDocument()->GetNextPos( nNewX
,nNewY
, nTab
, -1,0, false,sal_True
, aMark
);
394 //! sonst Exception oder so
396 SetNewRange( ScRange( nNewX
, nNewY
, nTab
) );
399 void SAL_CALL
ScCellCursorObj::gotoOffset( sal_Int32 nColumnOffset
, sal_Int32 nRowOffset
)
400 throw(uno::RuntimeException
)
402 SolarMutexGuard aGuard
;
403 const ScRangeList
& rRanges
= GetRangeList();
404 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
405 ScRange
aOneRange( *rRanges
[ 0 ] );
408 if ( aOneRange
.aStart
.Col() + nColumnOffset
>= 0 &&
409 aOneRange
.aEnd
.Col() + nColumnOffset
<= MAXCOL
&&
410 aOneRange
.aStart
.Row() + nRowOffset
>= 0 &&
411 aOneRange
.aEnd
.Row() + nRowOffset
<= MAXROW
)
413 ScRange
aNew( (SCCOL
)(aOneRange
.aStart
.Col() + nColumnOffset
),
414 (SCROW
)(aOneRange
.aStart
.Row() + nRowOffset
),
415 aOneRange
.aStart
.Tab(),
416 (SCCOL
)(aOneRange
.aEnd
.Col() + nColumnOffset
),
417 (SCROW
)(aOneRange
.aEnd
.Row() + nRowOffset
),
418 aOneRange
.aEnd
.Tab() );
425 uno::Reference
<sheet::XSpreadsheet
> SAL_CALL
ScCellCursorObj::getSpreadsheet()
426 throw(uno::RuntimeException
)
428 SolarMutexGuard aGuard
;
429 return ScCellRangeObj::getSpreadsheet();
434 uno::Reference
<table::XCell
> SAL_CALL
ScCellCursorObj::getCellByPosition(
435 sal_Int32 nColumn
, sal_Int32 nRow
)
436 throw(lang::IndexOutOfBoundsException
, uno::RuntimeException
)
438 SolarMutexGuard aGuard
;
439 return ScCellRangeObj::getCellByPosition(nColumn
,nRow
);
442 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
)
446 SolarMutexGuard aGuard
;
447 return ScCellRangeObj::getCellRangeByPosition(nLeft
,nTop
,nRight
,nBottom
);
450 uno::Reference
<table::XCellRange
> SAL_CALL
ScCellCursorObj::getCellRangeByName(
451 const OUString
& rRange
) throw(uno::RuntimeException
)
453 SolarMutexGuard aGuard
;
454 return ScCellRangeObj::getCellRangeByName(rRange
);
459 OUString SAL_CALL
ScCellCursorObj::getImplementationName() throw(uno::RuntimeException
)
461 return OUString( "ScCellCursorObj" );
464 sal_Bool SAL_CALL
ScCellCursorObj::supportsService( const OUString
& rServiceName
)
465 throw(uno::RuntimeException
)
467 return rServiceName
.equalsAscii( SCSHEETCELLCURSOR_SERVICE
) ||
468 rServiceName
.equalsAscii( SCCELLCURSOR_SERVICE
) ||
469 ScCellRangeObj::supportsService(rServiceName
);
472 uno::Sequence
<OUString
> SAL_CALL
ScCellCursorObj::getSupportedServiceNames()
473 throw(uno::RuntimeException
)
475 // get all service names from cell range
476 uno::Sequence
<OUString
> aParentSeq(ScCellRangeObj::getSupportedServiceNames());
477 sal_Int32 nParentLen
= aParentSeq
.getLength();
478 const OUString
* pParentArr
= aParentSeq
.getConstArray();
480 // SheetCellCursor should be first (?)
481 uno::Sequence
<OUString
> aTotalSeq( nParentLen
+ 2 );
482 OUString
* pTotalArr
= aTotalSeq
.getArray();
483 pTotalArr
[0] = OUString( SCSHEETCELLCURSOR_SERVICE
);
484 pTotalArr
[1] = OUString( SCCELLCURSOR_SERVICE
);
486 // append cell range services
487 for (long i
=0; i
<nParentLen
; i
++)
488 pTotalArr
[i
+2] = pParentArr
[i
];
496 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */