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 <vcl/svapp.hxx>
21 #include <comphelper/sequence.hxx>
22 #include <cppuhelper/supportsservice.hxx>
23 #include <cppuhelper/queryinterface.hxx>
24 #include <cursuno.hxx>
25 #include <cellsuno.hxx>
27 #include <markdata.hxx>
29 using namespace com::sun::star
;
31 constexpr OUString SCSHEETCELLCURSOR_SERVICE
= u
"com.sun.star.sheet.SheetCellCursor"_ustr
;
32 constexpr OUString SCCELLCURSOR_SERVICE
= u
"com.sun.star.table.CellCursor"_ustr
;
34 ScCellCursorObj::ScCellCursorObj(ScDocShell
* pDocSh
, const ScRange
& rR
) :
35 ScCellCursorObj_BASE( pDocSh
, rR
)
39 ScCellCursorObj::~ScCellCursorObj()
45 void SAL_CALL
ScCellCursorObj::collapseToCurrentRegion()
47 SolarMutexGuard aGuard
;
48 const ScRangeList
& rRanges
= GetRangeList();
49 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
50 ScRange
aOneRange( rRanges
[ 0 ] );
52 aOneRange
.PutInOrder();
53 ScDocShell
* pDocSh
= GetDocShell();
57 SCCOL nStartCol
= aOneRange
.aStart
.Col();
58 SCROW nStartRow
= aOneRange
.aStart
.Row();
59 SCCOL nEndCol
= aOneRange
.aEnd
.Col();
60 SCROW nEndRow
= aOneRange
.aEnd
.Row();
61 SCTAB nTab
= aOneRange
.aStart
.Tab();
63 pDocSh
->GetDocument().GetDataArea(
64 nTab
, nStartCol
, nStartRow
, nEndCol
, nEndRow
, true, false );
66 ScRange
aNew( nStartCol
, nStartRow
, nTab
, nEndCol
, nEndRow
, nTab
);
70 void SAL_CALL
ScCellCursorObj::collapseToCurrentArray()
72 SolarMutexGuard aGuard
;
73 const ScRangeList
& rRanges
= GetRangeList();
74 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
75 ScRange
aOneRange( rRanges
[ 0 ] );
77 aOneRange
.PutInOrder();
78 ScAddress
aCursor(aOneRange
.aStart
); // use the start address of the range
80 ScDocShell
* pDocSh
= GetDocShell();
83 ScDocument
& rDoc
= pDocSh
->GetDocument();
86 // finding the matrix range is now in GetMatrixFormulaRange in the document
87 if ( rDoc
.GetMatrixFormulaRange( aCursor
, aMatrix
) )
89 SetNewRange( aMatrix
);
92 // that's a Bug, that this assertion comes; the API Reference says, that
93 // if there is no Matrix, the Range is left unchanged; they say nothing
97 OSL_FAIL("no matrix");
98 //! Exception, or what?
102 void SAL_CALL
ScCellCursorObj::collapseToMergedArea()
104 SolarMutexGuard aGuard
;
105 ScDocShell
* pDocSh
= GetDocShell();
108 const ScRangeList
& rRanges
= GetRangeList();
109 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
110 ScRange
aNewRange( rRanges
[ 0 ] );
112 ScDocument
& rDoc
= pDocSh
->GetDocument();
113 rDoc
.ExtendOverlapped( aNewRange
);
114 rDoc
.ExtendMerge( aNewRange
); // after ExtendOverlapped!
116 SetNewRange( aNewRange
);
120 void SAL_CALL
ScCellCursorObj::expandToEntireColumns()
122 SolarMutexGuard aGuard
;
123 const ScRangeList
& rRanges
= GetRangeList();
124 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
125 ScRange
aNewRange( rRanges
[ 0 ] );
127 aNewRange
.aStart
.SetRow( 0 );
128 aNewRange
.aEnd
.SetRow( GetDocShell()->GetDocument().MaxRow() );
130 SetNewRange( aNewRange
);
133 void SAL_CALL
ScCellCursorObj::expandToEntireRows()
135 SolarMutexGuard aGuard
;
136 const ScRangeList
& rRanges
= GetRangeList();
137 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
138 ScRange
aNewRange( rRanges
[ 0 ] );
140 aNewRange
.aStart
.SetCol( 0 );
141 aNewRange
.aEnd
.SetCol( GetDocShell()->GetDocument().MaxCol() );
143 SetNewRange( aNewRange
);
146 void SAL_CALL
ScCellCursorObj::collapseToSize( sal_Int32 nColumns
, sal_Int32 nRows
)
148 SolarMutexGuard aGuard
;
149 if ( nColumns
<= 0 || nRows
<= 0 )
151 OSL_FAIL("Empty range not allowed");
156 const ScRangeList
& rRanges
= GetRangeList();
157 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
158 ScRange
aNewRange( rRanges
[ 0 ] );
160 aNewRange
.PutInOrder(); //! really?
162 const auto & rDoc
= GetDocShell()->GetDocument();
163 tools::Long nEndX
= aNewRange
.aStart
.Col() + nColumns
- 1;
164 tools::Long nEndY
= aNewRange
.aStart
.Row() + nRows
- 1;
165 if ( nEndX
< 0 ) nEndX
= 0;
166 if ( nEndX
> rDoc
.MaxCol() ) nEndX
= rDoc
.MaxCol();
167 if ( nEndY
< 0 ) nEndY
= 0;
168 if ( nEndY
> rDoc
.MaxRow() ) nEndY
= rDoc
.MaxRow();
169 //! error/exception or so, if too big/small
171 aNewRange
.aEnd
.SetCol(static_cast<SCCOL
>(nEndX
));
172 aNewRange
.aEnd
.SetRow(static_cast<SCROW
>(nEndY
));
174 aNewRange
.PutInOrder(); //! really?
176 SetNewRange( aNewRange
);
182 void SAL_CALL
ScCellCursorObj::gotoStartOfUsedArea(sal_Bool bExpand
)
184 SolarMutexGuard aGuard
;
185 ScDocShell
* pDocSh
= GetDocShell();
189 const ScRangeList
& rRanges
= GetRangeList();
190 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
191 ScRange
aNewRange( rRanges
[0] );
192 SCTAB nTab
= aNewRange
.aStart
.Tab();
194 SCCOL nUsedX
= 0; // fetch the beginning
196 if (!pDocSh
->GetDocument().GetDataStart( nTab
, nUsedX
, nUsedY
))
202 aNewRange
.aStart
.SetCol( nUsedX
);
203 aNewRange
.aStart
.SetRow( nUsedY
);
205 aNewRange
.aEnd
= aNewRange
.aStart
;
206 SetNewRange( aNewRange
);
209 void SAL_CALL
ScCellCursorObj::gotoEndOfUsedArea( sal_Bool bExpand
)
211 SolarMutexGuard aGuard
;
212 ScDocShell
* pDocSh
= GetDocShell();
216 const ScRangeList
& rRanges
= GetRangeList();
217 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
218 ScRange
aNewRange( rRanges
[ 0 ]);
219 SCTAB nTab
= aNewRange
.aStart
.Tab();
221 SCCOL nUsedX
= 0; // fetch the end
223 if (!pDocSh
->GetDocument().GetTableArea( nTab
, nUsedX
, nUsedY
, true ))
229 aNewRange
.aEnd
.SetCol( nUsedX
);
230 aNewRange
.aEnd
.SetRow( nUsedY
);
232 aNewRange
.aStart
= aNewRange
.aEnd
;
233 SetNewRange( aNewRange
);
238 void SAL_CALL
ScCellCursorObj::gotoStart()
240 // this is similar to collapseToCurrentRegion
241 //! something like gotoEdge with 4 possible directions is needed
243 SolarMutexGuard aGuard
;
244 const ScRangeList
& rRanges
= GetRangeList();
245 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
246 ScRange
aOneRange( rRanges
[ 0 ]);
248 aOneRange
.PutInOrder();
249 ScDocShell
* pDocSh
= GetDocShell();
253 SCCOL nStartCol
= aOneRange
.aStart
.Col();
254 SCROW nStartRow
= aOneRange
.aStart
.Row();
255 SCCOL nEndCol
= aOneRange
.aEnd
.Col();
256 SCROW nEndRow
= aOneRange
.aEnd
.Row();
257 SCTAB nTab
= aOneRange
.aStart
.Tab();
259 pDocSh
->GetDocument().GetDataArea(
260 nTab
, nStartCol
, nStartRow
, nEndCol
, nEndRow
, false, false );
262 ScRange
aNew( nStartCol
, nStartRow
, nTab
);
266 void SAL_CALL
ScCellCursorObj::gotoEnd()
268 // this is similar to collapseToCurrentRegion
269 //! something like gotoEdge with 4 possible directions is needed
271 SolarMutexGuard aGuard
;
272 const ScRangeList
& rRanges
= GetRangeList();
273 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
274 ScRange
aOneRange( rRanges
[ 0 ] );
276 aOneRange
.PutInOrder();
277 ScDocShell
* pDocSh
= GetDocShell();
281 SCCOL nStartCol
= aOneRange
.aStart
.Col();
282 SCROW nStartRow
= aOneRange
.aStart
.Row();
283 SCCOL nEndCol
= aOneRange
.aEnd
.Col();
284 SCROW nEndRow
= aOneRange
.aEnd
.Row();
285 SCTAB nTab
= aOneRange
.aStart
.Tab();
287 pDocSh
->GetDocument().GetDataArea(
288 nTab
, nStartCol
, nStartRow
, nEndCol
, nEndRow
, false, false );
290 ScRange
aNew( nEndCol
, nEndRow
, nTab
);
294 void SAL_CALL
ScCellCursorObj::gotoNext()
296 SolarMutexGuard aGuard
;
297 const ScRangeList
& rRanges
= GetRangeList();
298 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
299 ScRange
aOneRange( rRanges
[ 0 ] );
301 aOneRange
.PutInOrder();
302 ScAddress
aCursor(aOneRange
.aStart
); // always use start of block
304 ScMarkData
aMark(GetDocument()->GetSheetLimits()); // not used with bMarked=FALSE
305 SCCOL nNewX
= aCursor
.Col();
306 SCROW nNewY
= aCursor
.Row();
307 SCTAB nTab
= aCursor
.Tab();
308 ScDocShell
* pDocSh
= GetDocShell();
310 pDocSh
->GetDocument().GetNextPos( nNewX
,nNewY
, nTab
, 1,0, false,true, aMark
);
311 //! otherwise exception or so
313 SetNewRange( ScRange( nNewX
, nNewY
, nTab
) );
316 void SAL_CALL
ScCellCursorObj::gotoPrevious()
318 SolarMutexGuard aGuard
;
319 const ScRangeList
& rRanges
= GetRangeList();
320 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
321 ScRange
aOneRange( rRanges
[ 0 ] );
323 aOneRange
.PutInOrder();
324 ScAddress
aCursor(aOneRange
.aStart
); // always use start of block
326 ScMarkData
aMark(GetDocument()->GetSheetLimits()); // not used with bMarked=FALSE
327 SCCOL nNewX
= aCursor
.Col();
328 SCROW nNewY
= aCursor
.Row();
329 SCTAB nTab
= aCursor
.Tab();
330 ScDocShell
* pDocSh
= GetDocShell();
332 pDocSh
->GetDocument().GetNextPos( nNewX
,nNewY
, nTab
, -1,0, false,true, aMark
);
333 //! otherwise exception or so
335 SetNewRange( ScRange( nNewX
, nNewY
, nTab
) );
338 void SAL_CALL
ScCellCursorObj::gotoOffset( sal_Int32 nColumnOffset
, sal_Int32 nRowOffset
)
340 SolarMutexGuard aGuard
;
341 const ScRangeList
& rRanges
= GetRangeList();
342 OSL_ENSURE( rRanges
.size() == 1, "Range? Ranges?" );
343 ScRange
aOneRange( rRanges
[ 0 ] );
344 aOneRange
.PutInOrder();
346 const auto & rDoc
= GetDocShell()->GetDocument();
347 if ( aOneRange
.aStart
.Col() + nColumnOffset
>= 0 &&
348 aOneRange
.aEnd
.Col() + nColumnOffset
<= rDoc
.MaxCol() &&
349 aOneRange
.aStart
.Row() + nRowOffset
>= 0 &&
350 aOneRange
.aEnd
.Row() + nRowOffset
<= rDoc
.MaxRow() )
352 ScRange
aNew( static_cast<SCCOL
>(aOneRange
.aStart
.Col() + nColumnOffset
),
353 static_cast<SCROW
>(aOneRange
.aStart
.Row() + nRowOffset
),
354 aOneRange
.aStart
.Tab(),
355 static_cast<SCCOL
>(aOneRange
.aEnd
.Col() + nColumnOffset
),
356 static_cast<SCROW
>(aOneRange
.aEnd
.Row() + nRowOffset
),
357 aOneRange
.aEnd
.Tab() );
364 uno::Reference
<sheet::XSpreadsheet
> SAL_CALL
ScCellCursorObj::getSpreadsheet()
366 SolarMutexGuard aGuard
;
367 return ScCellRangeObj::getSpreadsheet();
372 uno::Reference
<table::XCell
> SAL_CALL
ScCellCursorObj::getCellByPosition(
373 sal_Int32 nColumn
, sal_Int32 nRow
)
375 SolarMutexGuard aGuard
;
376 return ScCellRangeObj::getCellByPosition(nColumn
,nRow
);
379 uno::Reference
<table::XCellRange
> SAL_CALL
ScCellCursorObj::getCellRangeByPosition(
380 sal_Int32 nLeft
, sal_Int32 nTop
, sal_Int32 nRight
, sal_Int32 nBottom
)
382 SolarMutexGuard aGuard
;
383 return ScCellRangeObj::getCellRangeByPosition(nLeft
,nTop
,nRight
,nBottom
);
386 uno::Reference
<table::XCellRange
> SAL_CALL
ScCellCursorObj::getCellRangeByName(
387 const OUString
& rRange
)
389 SolarMutexGuard aGuard
;
390 return ScCellRangeObj::getCellRangeByName(rRange
);
395 OUString SAL_CALL
ScCellCursorObj::getImplementationName()
397 return u
"ScCellCursorObj"_ustr
;
400 sal_Bool SAL_CALL
ScCellCursorObj::supportsService( const OUString
& rServiceName
)
402 return cppu::supportsService(this, rServiceName
);
405 uno::Sequence
<OUString
> SAL_CALL
ScCellCursorObj::getSupportedServiceNames()
407 // SheetCellCursor should be first (?)
408 return comphelper::concatSequences
<OUString
>(
409 { SCSHEETCELLCURSOR_SERVICE
, SCCELLCURSOR_SERVICE
},
410 ScCellRangeObj::getSupportedServiceNames());
413 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */