1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: cursuno.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
36 #include "scitems.hxx"
37 #include <svtools/intitem.hxx>
38 #include <svtools/zforlist.hxx>
41 #include "cursuno.hxx"
42 #include "cellsuno.hxx"
45 #include "markdata.hxx"
46 #include "dociter.hxx"
47 #include "unoguard.hxx"
48 #include "miscuno.hxx"
50 using namespace com::sun::star
;
52 //------------------------------------------------------------------------
54 #define SCSHEETCELLCURSOR_SERVICE "com.sun.star.sheet.SheetCellCursor"
55 #define SCCELLCURSOR_SERVICE "com.sun.star.table.CellCursor"
57 //------------------------------------------------------------------------
59 ScCellCursorObj::ScCellCursorObj(ScDocShell
* pDocSh
, const ScRange
& rR
) :
60 ScCellRangeObj( pDocSh
, rR
)
64 ScCellCursorObj::~ScCellCursorObj()
68 uno::Any SAL_CALL
ScCellCursorObj::queryInterface( const uno::Type
& rType
) throw(uno::RuntimeException
)
70 SC_QUERYINTERFACE( sheet::XSheetCellCursor
)
71 SC_QUERYINTERFACE( sheet::XUsedAreaCursor
)
72 SC_QUERYINTERFACE( table::XCellCursor
)
74 return ScCellRangeObj::queryInterface( rType
);
77 void SAL_CALL
ScCellCursorObj::acquire() throw()
79 ScCellRangeObj::acquire();
82 void SAL_CALL
ScCellCursorObj::release() throw()
84 ScCellRangeObj::release();
87 uno::Sequence
<uno::Type
> SAL_CALL
ScCellCursorObj::getTypes() throw(uno::RuntimeException
)
89 static uno::Sequence
<uno::Type
> aTypes
;
90 if ( aTypes
.getLength() == 0 )
92 uno::Sequence
<uno::Type
> aParentTypes(ScCellRangeObj::getTypes());
93 long nParentLen
= aParentTypes
.getLength();
94 const uno::Type
* pParentPtr
= aParentTypes
.getConstArray();
96 aTypes
.realloc( nParentLen
+ 3 );
97 uno::Type
* pPtr
= aTypes
.getArray();
98 pPtr
[nParentLen
+ 0] = getCppuType((const uno::Reference
<sheet::XSheetCellCursor
>*)0);
99 pPtr
[nParentLen
+ 1] = getCppuType((const uno::Reference
<sheet::XUsedAreaCursor
>*)0);
100 pPtr
[nParentLen
+ 2] = getCppuType((const uno::Reference
<table::XCellCursor
>*)0);
102 for (long i
=0; i
<nParentLen
; i
++)
103 pPtr
[i
] = pParentPtr
[i
]; // parent types first
108 uno::Sequence
<sal_Int8
> SAL_CALL
ScCellCursorObj::getImplementationId() throw(uno::RuntimeException
)
110 static uno::Sequence
< sal_Int8
> aId
;
111 if( aId
.getLength() == 0 )
114 rtl_createUuid( (sal_uInt8
*)aId
.getArray(), 0, sal_True
);
121 void SAL_CALL
ScCellCursorObj::collapseToCurrentRegion() throw(uno::RuntimeException
)
124 const ScRangeList
& rRanges
= GetRangeList();
125 DBG_ASSERT( rRanges
.Count() == 1, "Range? Ranges?" );
126 ScRange
aOneRange(*rRanges
.GetObject(0));
129 ScDocShell
* pDocSh
= GetDocShell();
132 SCCOL nStartCol
= aOneRange
.aStart
.Col();
133 SCROW nStartRow
= aOneRange
.aStart
.Row();
134 SCCOL nEndCol
= aOneRange
.aEnd
.Col();
135 SCROW nEndRow
= aOneRange
.aEnd
.Row();
136 SCTAB nTab
= aOneRange
.aStart
.Tab();
138 pDocSh
->GetDocument()->GetDataArea(
139 nTab
, nStartCol
, nStartRow
, nEndCol
, nEndRow
, TRUE
);
141 ScRange
aNew( nStartCol
, nStartRow
, nTab
, nEndCol
, nEndRow
, nTab
);
146 void SAL_CALL
ScCellCursorObj::collapseToCurrentArray() throw(uno::RuntimeException
)
149 const ScRangeList
& rRanges
= GetRangeList();
150 DBG_ASSERT( rRanges
.Count() == 1, "Range? Ranges?" );
151 ScRange
aOneRange(*rRanges
.GetObject(0));
154 ScAddress
aCursor(aOneRange
.aStart
); // use the start address of the range
156 ScDocShell
* pDocSh
= GetDocShell();
159 ScDocument
* pDoc
= pDocSh
->GetDocument();
162 // finding the matrix range is now in GetMatrixFormulaRange in the document
163 if ( pDoc
->GetMatrixFormulaRange( aCursor
, aMatrix
) )
165 SetNewRange( aMatrix
);
168 // thats a Bug, that this assertion comes; the API Reference says, that
169 // if there is no Matrix, the Range is left unchanged; they says nothing
173 DBG_ERROR("keine Matrix");
174 //! Exception, oder was?
178 void SAL_CALL
ScCellCursorObj::collapseToMergedArea() throw(uno::RuntimeException
)
181 ScDocShell
* pDocSh
= GetDocShell();
184 const ScRangeList
& rRanges
= GetRangeList();
185 DBG_ASSERT( rRanges
.Count() == 1, "Range? Ranges?" );
186 ScRange
aNewRange(*rRanges
.GetObject(0));
188 ScDocument
* pDoc
= pDocSh
->GetDocument();
189 pDoc
->ExtendOverlapped( aNewRange
);
190 pDoc
->ExtendMerge( aNewRange
); // after ExtendOverlapped!
192 SetNewRange( aNewRange
);
196 void SAL_CALL
ScCellCursorObj::expandToEntireColumns() throw(uno::RuntimeException
)
199 const ScRangeList
& rRanges
= GetRangeList();
200 DBG_ASSERT( rRanges
.Count() == 1, "Range? Ranges?" );
201 ScRange
aNewRange(*rRanges
.GetObject(0));
203 aNewRange
.aStart
.SetRow( 0 );
204 aNewRange
.aEnd
.SetRow( MAXROW
);
206 SetNewRange( aNewRange
);
209 void SAL_CALL
ScCellCursorObj::expandToEntireRows() throw(uno::RuntimeException
)
212 const ScRangeList
& rRanges
= GetRangeList();
213 DBG_ASSERT( rRanges
.Count() == 1, "Range? Ranges?" );
214 ScRange
aNewRange(*rRanges
.GetObject(0));
216 aNewRange
.aStart
.SetCol( 0 );
217 aNewRange
.aEnd
.SetCol( MAXCOL
);
219 SetNewRange( aNewRange
);
222 void SAL_CALL
ScCellCursorObj::collapseToSize( sal_Int32 nColumns
, sal_Int32 nRows
)
223 throw(uno::RuntimeException
)
226 if ( nColumns
<= 0 || nRows
<= 0 )
228 DBG_ERROR("leerer Range geht nicht");
233 const ScRangeList
& rRanges
= GetRangeList();
234 DBG_ASSERT( rRanges
.Count() == 1, "Range? Ranges?" );
235 ScRange
aNewRange(*rRanges
.GetObject(0));
237 aNewRange
.Justify(); //! wirklich?
239 long nEndX
= aNewRange
.aStart
.Col() + nColumns
- 1;
240 long nEndY
= aNewRange
.aStart
.Row() + nRows
- 1;
241 if ( nEndX
< 0 ) nEndX
= 0;
242 if ( nEndX
> MAXCOL
) nEndX
= MAXCOL
;
243 if ( nEndY
< 0 ) nEndY
= 0;
244 if ( nEndY
> MAXROW
) nEndY
= MAXROW
;
245 //! Fehler/Exception oder so, wenn zu gross/zu klein?
247 aNewRange
.aEnd
.SetCol((SCCOL
)nEndX
);
248 aNewRange
.aEnd
.SetRow((SCROW
)nEndY
);
250 aNewRange
.Justify(); //! wirklich?
252 SetNewRange( aNewRange
);
258 void SAL_CALL
ScCellCursorObj::gotoStartOfUsedArea( sal_Bool bExpand
)
259 throw(uno::RuntimeException
)
262 ScDocShell
* pDocSh
= GetDocShell();
265 const ScRangeList
& rRanges
= GetRangeList();
266 DBG_ASSERT( rRanges
.Count() == 1, "Range? Ranges?" );
267 ScRange
aNewRange(*rRanges
.GetObject(0));
268 SCTAB nTab
= aNewRange
.aStart
.Tab();
270 SCCOL nUsedX
= 0; // Anfang holen
272 if (!pDocSh
->GetDocument()->GetDataStart( nTab
, nUsedX
, nUsedY
))
278 aNewRange
.aStart
.SetCol( nUsedX
);
279 aNewRange
.aStart
.SetRow( nUsedY
);
281 aNewRange
.aEnd
= aNewRange
.aStart
;
282 SetNewRange( aNewRange
);
286 void SAL_CALL
ScCellCursorObj::gotoEndOfUsedArea( sal_Bool bExpand
)
287 throw(uno::RuntimeException
)
290 ScDocShell
* pDocSh
= GetDocShell();
293 const ScRangeList
& rRanges
= GetRangeList();
294 DBG_ASSERT( rRanges
.Count() == 1, "Range? Ranges?" );
295 ScRange
aNewRange(*rRanges
.GetObject(0));
296 SCTAB nTab
= aNewRange
.aStart
.Tab();
298 SCCOL nUsedX
= 0; // Ende holen
300 if (!pDocSh
->GetDocument()->GetTableArea( nTab
, nUsedX
, nUsedY
))
306 aNewRange
.aEnd
.SetCol( nUsedX
);
307 aNewRange
.aEnd
.SetRow( nUsedY
);
309 aNewRange
.aStart
= aNewRange
.aEnd
;
310 SetNewRange( aNewRange
);
316 void SAL_CALL
ScCellCursorObj::gotoStart() throw(uno::RuntimeException
)
318 // this is similar to collapseToCurrentRegion
319 //! something like gotoEdge with 4 possible directions is needed
322 const ScRangeList
& rRanges
= GetRangeList();
323 DBG_ASSERT( rRanges
.Count() == 1, "Range? Ranges?" );
324 ScRange
aOneRange(*rRanges
.GetObject(0));
327 ScDocShell
* pDocSh
= GetDocShell();
330 SCCOL nStartCol
= aOneRange
.aStart
.Col();
331 SCROW nStartRow
= aOneRange
.aStart
.Row();
332 SCCOL nEndCol
= aOneRange
.aEnd
.Col();
333 SCROW nEndRow
= aOneRange
.aEnd
.Row();
334 SCTAB nTab
= aOneRange
.aStart
.Tab();
336 pDocSh
->GetDocument()->GetDataArea(
337 nTab
, nStartCol
, nStartRow
, nEndCol
, nEndRow
, FALSE
);
339 ScRange
aNew( nStartCol
, nStartRow
, nTab
);
344 void SAL_CALL
ScCellCursorObj::gotoEnd() throw(uno::RuntimeException
)
346 // this is similar to collapseToCurrentRegion
347 //! something like gotoEdge with 4 possible directions is needed
350 const ScRangeList
& rRanges
= GetRangeList();
351 DBG_ASSERT( rRanges
.Count() == 1, "Range? Ranges?" );
352 ScRange
aOneRange(*rRanges
.GetObject(0));
355 ScDocShell
* pDocSh
= GetDocShell();
358 SCCOL nStartCol
= aOneRange
.aStart
.Col();
359 SCROW nStartRow
= aOneRange
.aStart
.Row();
360 SCCOL nEndCol
= aOneRange
.aEnd
.Col();
361 SCROW nEndRow
= aOneRange
.aEnd
.Row();
362 SCTAB nTab
= aOneRange
.aStart
.Tab();
364 pDocSh
->GetDocument()->GetDataArea(
365 nTab
, nStartCol
, nStartRow
, nEndCol
, nEndRow
, FALSE
);
367 ScRange
aNew( nEndCol
, nEndRow
, nTab
);
372 void SAL_CALL
ScCellCursorObj::gotoNext() throw(uno::RuntimeException
)
375 const ScRangeList
& rRanges
= GetRangeList();
376 DBG_ASSERT( rRanges
.Count() == 1, "Range? Ranges?" );
377 ScRange
aOneRange(*rRanges
.GetObject(0));
380 ScAddress
aCursor(aOneRange
.aStart
); // bei Block immer den Start nehmen
382 ScMarkData aMark
; // not used with bMarked=FALSE
383 SCCOL nNewX
= aCursor
.Col();
384 SCROW nNewY
= aCursor
.Row();
385 SCTAB nTab
= aCursor
.Tab();
386 ScDocShell
* pDocSh
= GetDocShell();
388 pDocSh
->GetDocument()->GetNextPos( nNewX
,nNewY
, nTab
, 1,0, FALSE
,TRUE
, aMark
);
389 //! sonst Exception oder so
391 SetNewRange( ScRange( nNewX
, nNewY
, nTab
) );
394 void SAL_CALL
ScCellCursorObj::gotoPrevious() throw(uno::RuntimeException
)
397 const ScRangeList
& rRanges
= GetRangeList();
398 DBG_ASSERT( rRanges
.Count() == 1, "Range? Ranges?" );
399 ScRange
aOneRange(*rRanges
.GetObject(0));
402 ScAddress
aCursor(aOneRange
.aStart
); // bei Block immer den Start nehmen
404 ScMarkData aMark
; // not used with bMarked=FALSE
405 SCCOL nNewX
= aCursor
.Col();
406 SCROW nNewY
= aCursor
.Row();
407 SCTAB nTab
= aCursor
.Tab();
408 ScDocShell
* pDocSh
= GetDocShell();
410 pDocSh
->GetDocument()->GetNextPos( nNewX
,nNewY
, nTab
, -1,0, FALSE
,TRUE
, aMark
);
411 //! sonst Exception oder so
413 SetNewRange( ScRange( nNewX
, nNewY
, nTab
) );
416 void SAL_CALL
ScCellCursorObj::gotoOffset( sal_Int32 nColumnOffset
, sal_Int32 nRowOffset
)
417 throw(uno::RuntimeException
)
420 const ScRangeList
& rRanges
= GetRangeList();
421 DBG_ASSERT( rRanges
.Count() == 1, "Range? Ranges?" );
422 ScRange
aOneRange(*rRanges
.GetObject(0));
425 if ( aOneRange
.aStart
.Col() + nColumnOffset
>= 0 &&
426 aOneRange
.aEnd
.Col() + nColumnOffset
<= MAXCOL
&&
427 aOneRange
.aStart
.Row() + nRowOffset
>= 0 &&
428 aOneRange
.aEnd
.Row() + nRowOffset
<= MAXROW
)
430 ScRange
aNew( (SCCOL
)(aOneRange
.aStart
.Col() + nColumnOffset
),
431 (SCROW
)(aOneRange
.aStart
.Row() + nRowOffset
),
432 aOneRange
.aStart
.Tab(),
433 (SCCOL
)(aOneRange
.aEnd
.Col() + nColumnOffset
),
434 (SCROW
)(aOneRange
.aEnd
.Row() + nRowOffset
),
435 aOneRange
.aEnd
.Tab() );
442 uno::Reference
<sheet::XSpreadsheet
> SAL_CALL
ScCellCursorObj::getSpreadsheet()
443 throw(uno::RuntimeException
)
446 return ScCellRangeObj::getSpreadsheet();
451 uno::Reference
<table::XCell
> SAL_CALL
ScCellCursorObj::getCellByPosition(
452 sal_Int32 nColumn
, sal_Int32 nRow
)
453 throw(lang::IndexOutOfBoundsException
, uno::RuntimeException
)
456 return ScCellRangeObj::getCellByPosition(nColumn
,nRow
);
459 uno::Reference
<table::XCellRange
> SAL_CALL
ScCellCursorObj::getCellRangeByPosition(
460 sal_Int32 nLeft
, sal_Int32 nTop
, sal_Int32 nRight
, sal_Int32 nBottom
)
461 throw(lang::IndexOutOfBoundsException
, uno::RuntimeException
)
464 return ScCellRangeObj::getCellRangeByPosition(nLeft
,nTop
,nRight
,nBottom
);
467 uno::Reference
<table::XCellRange
> SAL_CALL
ScCellCursorObj::getCellRangeByName(
468 const rtl::OUString
& rRange
) throw(uno::RuntimeException
)
471 return ScCellRangeObj::getCellRangeByName(rRange
);
476 rtl::OUString SAL_CALL
ScCellCursorObj::getImplementationName() throw(uno::RuntimeException
)
478 return rtl::OUString::createFromAscii( "ScCellCursorObj" );
481 sal_Bool SAL_CALL
ScCellCursorObj::supportsService( const rtl::OUString
& rServiceName
)
482 throw(uno::RuntimeException
)
484 String
aServiceStr( rServiceName
);
485 return aServiceStr
.EqualsAscii( SCSHEETCELLCURSOR_SERVICE
) ||
486 aServiceStr
.EqualsAscii( SCCELLCURSOR_SERVICE
) ||
487 ScCellRangeObj::supportsService(rServiceName
);
490 uno::Sequence
<rtl::OUString
> SAL_CALL
ScCellCursorObj::getSupportedServiceNames()
491 throw(uno::RuntimeException
)
493 // get all service names from cell range
494 uno::Sequence
<rtl::OUString
> aParentSeq(ScCellRangeObj::getSupportedServiceNames());
495 sal_Int32 nParentLen
= aParentSeq
.getLength();
496 const rtl::OUString
* pParentArr
= aParentSeq
.getConstArray();
498 // SheetCellCursor should be first (?)
499 uno::Sequence
<rtl::OUString
> aTotalSeq( nParentLen
+ 2 );
500 rtl::OUString
* pTotalArr
= aTotalSeq
.getArray();
501 pTotalArr
[0] = rtl::OUString::createFromAscii( SCSHEETCELLCURSOR_SERVICE
);
502 pTotalArr
[1] = rtl::OUString::createFromAscii( SCCELLCURSOR_SERVICE
);
504 // append cell range services
505 for (long i
=0; i
<nParentLen
; i
++)
506 pTotalArr
[i
+2] = pParentArr
[i
];