diff options
Diffstat (limited to 'sc/source/ui/unoobj/cursuno.cxx')
-rw-r--r-- | sc/source/ui/unoobj/cursuno.cxx | 450 |
1 files changed, 450 insertions, 0 deletions
diff --git a/sc/source/ui/unoobj/cursuno.cxx b/sc/source/ui/unoobj/cursuno.cxx new file mode 100644 index 000000000..800b4be82 --- /dev/null +++ b/sc/source/ui/unoobj/cursuno.cxx @@ -0,0 +1,450 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <vcl/svapp.hxx> +#include <comphelper/sequence.hxx> +#include <cppuhelper/supportsservice.hxx> + +#include <cursuno.hxx> +#include <cellsuno.hxx> +#include <docsh.hxx> +#include <markdata.hxx> +#include <miscuno.hxx> + +using namespace com::sun::star; + +constexpr OUStringLiteral SCSHEETCELLCURSOR_SERVICE = u"com.sun.star.sheet.SheetCellCursor"; +constexpr OUStringLiteral SCCELLCURSOR_SERVICE = u"com.sun.star.table.CellCursor"; + +ScCellCursorObj::ScCellCursorObj(ScDocShell* pDocSh, const ScRange& rR) : + ScCellRangeObj( pDocSh, rR ) +{ +} + +ScCellCursorObj::~ScCellCursorObj() +{ +} + +uno::Any SAL_CALL ScCellCursorObj::queryInterface( const uno::Type& rType ) +{ + SC_QUERYINTERFACE( sheet::XSheetCellCursor ) + SC_QUERYINTERFACE( sheet::XUsedAreaCursor ) + SC_QUERYINTERFACE( table::XCellCursor ) + + return ScCellRangeObj::queryInterface( rType ); +} + +void SAL_CALL ScCellCursorObj::acquire() noexcept +{ + ScCellRangeObj::acquire(); +} + +void SAL_CALL ScCellCursorObj::release() noexcept +{ + ScCellRangeObj::release(); +} + +uno::Sequence<uno::Type> SAL_CALL ScCellCursorObj::getTypes() +{ + return comphelper::concatSequences( + ScCellRangeObj::getTypes(), + uno::Sequence<uno::Type> + { + cppu::UnoType<sheet::XSheetCellCursor>::get(), + cppu::UnoType<sheet::XUsedAreaCursor>::get(), + cppu::UnoType<table::XCellCursor>::get() + } ); +} + +uno::Sequence<sal_Int8> SAL_CALL ScCellCursorObj::getImplementationId() +{ + return css::uno::Sequence<sal_Int8>(); +} + +// XSheetCellCursor + +void SAL_CALL ScCellCursorObj::collapseToCurrentRegion() +{ + SolarMutexGuard aGuard; + const ScRangeList& rRanges = GetRangeList(); + OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" ); + ScRange aOneRange( rRanges[ 0 ] ); + + aOneRange.PutInOrder(); + ScDocShell* pDocSh = GetDocShell(); + if ( !pDocSh ) + return; + + SCCOL nStartCol = aOneRange.aStart.Col(); + SCROW nStartRow = aOneRange.aStart.Row(); + SCCOL nEndCol = aOneRange.aEnd.Col(); + SCROW nEndRow = aOneRange.aEnd.Row(); + SCTAB nTab = aOneRange.aStart.Tab(); + + pDocSh->GetDocument().GetDataArea( + nTab, nStartCol, nStartRow, nEndCol, nEndRow, true, false ); + + ScRange aNew( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab ); + SetNewRange( aNew ); +} + +void SAL_CALL ScCellCursorObj::collapseToCurrentArray() +{ + SolarMutexGuard aGuard; + const ScRangeList& rRanges = GetRangeList(); + OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" ); + ScRange aOneRange( rRanges[ 0 ] ); + + aOneRange.PutInOrder(); + ScAddress aCursor(aOneRange.aStart); // use the start address of the range + + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocument& rDoc = pDocSh->GetDocument(); + ScRange aMatrix; + + // finding the matrix range is now in GetMatrixFormulaRange in the document + if ( rDoc.GetMatrixFormulaRange( aCursor, aMatrix ) ) + { + SetNewRange( aMatrix ); + } + } + // that's a Bug, that this assertion comes; the API Reference says, that + // if there is no Matrix, the Range is left unchanged; they say nothing + // about an exception + /*if (!bFound) + { + OSL_FAIL("no matrix"); + //! Exception, or what? + }*/ +} + +void SAL_CALL ScCellCursorObj::collapseToMergedArea() +{ + SolarMutexGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + const ScRangeList& rRanges = GetRangeList(); + OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" ); + ScRange aNewRange( rRanges[ 0 ] ); + + ScDocument& rDoc = pDocSh->GetDocument(); + rDoc.ExtendOverlapped( aNewRange ); + rDoc.ExtendMerge( aNewRange ); // after ExtendOverlapped! + + SetNewRange( aNewRange ); + } +} + +void SAL_CALL ScCellCursorObj::expandToEntireColumns() +{ + SolarMutexGuard aGuard; + const ScRangeList& rRanges = GetRangeList(); + OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" ); + ScRange aNewRange( rRanges[ 0 ] ); + + aNewRange.aStart.SetRow( 0 ); + aNewRange.aEnd.SetRow( GetDocShell()->GetDocument().MaxRow() ); + + SetNewRange( aNewRange ); +} + +void SAL_CALL ScCellCursorObj::expandToEntireRows() +{ + SolarMutexGuard aGuard; + const ScRangeList& rRanges = GetRangeList(); + OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" ); + ScRange aNewRange( rRanges[ 0 ] ); + + aNewRange.aStart.SetCol( 0 ); + aNewRange.aEnd.SetCol( GetDocShell()->GetDocument().MaxCol() ); + + SetNewRange( aNewRange ); +} + +void SAL_CALL ScCellCursorObj::collapseToSize( sal_Int32 nColumns, sal_Int32 nRows ) +{ + SolarMutexGuard aGuard; + if ( nColumns <= 0 || nRows <= 0 ) + { + OSL_FAIL("Empty range not allowed"); + //! and then? + } + else + { + const ScRangeList& rRanges = GetRangeList(); + OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" ); + ScRange aNewRange( rRanges[ 0 ] ); + + aNewRange.PutInOrder(); //! really? + + const auto & rDoc = GetDocShell()->GetDocument(); + tools::Long nEndX = aNewRange.aStart.Col() + nColumns - 1; + tools::Long nEndY = aNewRange.aStart.Row() + nRows - 1; + if ( nEndX < 0 ) nEndX = 0; + if ( nEndX > rDoc.MaxCol() ) nEndX = rDoc.MaxCol(); + if ( nEndY < 0 ) nEndY = 0; + if ( nEndY > rDoc.MaxRow() ) nEndY = rDoc.MaxRow(); + //! error/exception or so, if too big/small + + aNewRange.aEnd.SetCol(static_cast<SCCOL>(nEndX)); + aNewRange.aEnd.SetRow(static_cast<SCROW>(nEndY)); + + aNewRange.PutInOrder(); //! really? + + SetNewRange( aNewRange ); + } +} + +// XUsedAreaCursor + +void SAL_CALL ScCellCursorObj::gotoStartOfUsedArea(sal_Bool bExpand) +{ + SolarMutexGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( !pDocSh ) + return; + + const ScRangeList& rRanges = GetRangeList(); + OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" ); + ScRange aNewRange( rRanges[0] ); + SCTAB nTab = aNewRange.aStart.Tab(); + + SCCOL nUsedX = 0; // fetch the beginning + SCROW nUsedY = 0; + if (!pDocSh->GetDocument().GetDataStart( nTab, nUsedX, nUsedY )) + { + nUsedX = 0; + nUsedY = 0; + } + + aNewRange.aStart.SetCol( nUsedX ); + aNewRange.aStart.SetRow( nUsedY ); + if (!bExpand) + aNewRange.aEnd = aNewRange.aStart; + SetNewRange( aNewRange ); +} + +void SAL_CALL ScCellCursorObj::gotoEndOfUsedArea( sal_Bool bExpand ) +{ + SolarMutexGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( !pDocSh ) + return; + + const ScRangeList& rRanges = GetRangeList(); + OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" ); + ScRange aNewRange( rRanges[ 0 ]); + SCTAB nTab = aNewRange.aStart.Tab(); + + SCCOL nUsedX = 0; // fetch the end + SCROW nUsedY = 0; + if (!pDocSh->GetDocument().GetTableArea( nTab, nUsedX, nUsedY, true )) + { + nUsedX = 0; + nUsedY = 0; + } + + aNewRange.aEnd.SetCol( nUsedX ); + aNewRange.aEnd.SetRow( nUsedY ); + if (!bExpand) + aNewRange.aStart = aNewRange.aEnd; + SetNewRange( aNewRange ); +} + +// XCellCursor + +void SAL_CALL ScCellCursorObj::gotoStart() +{ + // this is similar to collapseToCurrentRegion + //! something like gotoEdge with 4 possible directions is needed + + SolarMutexGuard aGuard; + const ScRangeList& rRanges = GetRangeList(); + OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" ); + ScRange aOneRange( rRanges[ 0 ]); + + aOneRange.PutInOrder(); + ScDocShell* pDocSh = GetDocShell(); + if ( !pDocSh ) + return; + + SCCOL nStartCol = aOneRange.aStart.Col(); + SCROW nStartRow = aOneRange.aStart.Row(); + SCCOL nEndCol = aOneRange.aEnd.Col(); + SCROW nEndRow = aOneRange.aEnd.Row(); + SCTAB nTab = aOneRange.aStart.Tab(); + + pDocSh->GetDocument().GetDataArea( + nTab, nStartCol, nStartRow, nEndCol, nEndRow, false, false ); + + ScRange aNew( nStartCol, nStartRow, nTab ); + SetNewRange( aNew ); +} + +void SAL_CALL ScCellCursorObj::gotoEnd() +{ + // this is similar to collapseToCurrentRegion + //! something like gotoEdge with 4 possible directions is needed + + SolarMutexGuard aGuard; + const ScRangeList& rRanges = GetRangeList(); + OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" ); + ScRange aOneRange( rRanges[ 0 ] ); + + aOneRange.PutInOrder(); + ScDocShell* pDocSh = GetDocShell(); + if ( !pDocSh ) + return; + + SCCOL nStartCol = aOneRange.aStart.Col(); + SCROW nStartRow = aOneRange.aStart.Row(); + SCCOL nEndCol = aOneRange.aEnd.Col(); + SCROW nEndRow = aOneRange.aEnd.Row(); + SCTAB nTab = aOneRange.aStart.Tab(); + + pDocSh->GetDocument().GetDataArea( + nTab, nStartCol, nStartRow, nEndCol, nEndRow, false, false ); + + ScRange aNew( nEndCol, nEndRow, nTab ); + SetNewRange( aNew ); +} + +void SAL_CALL ScCellCursorObj::gotoNext() +{ + SolarMutexGuard aGuard; + const ScRangeList& rRanges = GetRangeList(); + OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" ); + ScRange aOneRange( rRanges[ 0 ] ); + + aOneRange.PutInOrder(); + ScAddress aCursor(aOneRange.aStart); // always use start of block + + ScMarkData aMark(GetDocument()->GetSheetLimits()); // not used with bMarked=FALSE + SCCOL nNewX = aCursor.Col(); + SCROW nNewY = aCursor.Row(); + SCTAB nTab = aCursor.Tab(); + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + pDocSh->GetDocument().GetNextPos( nNewX,nNewY, nTab, 1,0, false,true, aMark ); + //! otherwise exception or so + + SetNewRange( ScRange( nNewX, nNewY, nTab ) ); +} + +void SAL_CALL ScCellCursorObj::gotoPrevious() +{ + SolarMutexGuard aGuard; + const ScRangeList& rRanges = GetRangeList(); + OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" ); + ScRange aOneRange( rRanges[ 0 ] ); + + aOneRange.PutInOrder(); + ScAddress aCursor(aOneRange.aStart); // always use start of block + + ScMarkData aMark(GetDocument()->GetSheetLimits()); // not used with bMarked=FALSE + SCCOL nNewX = aCursor.Col(); + SCROW nNewY = aCursor.Row(); + SCTAB nTab = aCursor.Tab(); + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + pDocSh->GetDocument().GetNextPos( nNewX,nNewY, nTab, -1,0, false,true, aMark ); + //! otherwise exception or so + + SetNewRange( ScRange( nNewX, nNewY, nTab ) ); +} + +void SAL_CALL ScCellCursorObj::gotoOffset( sal_Int32 nColumnOffset, sal_Int32 nRowOffset ) +{ + SolarMutexGuard aGuard; + const ScRangeList& rRanges = GetRangeList(); + OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" ); + ScRange aOneRange( rRanges[ 0 ] ); + aOneRange.PutInOrder(); + + const auto & rDoc = GetDocShell()->GetDocument(); + if ( aOneRange.aStart.Col() + nColumnOffset >= 0 && + aOneRange.aEnd.Col() + nColumnOffset <= rDoc.MaxCol() && + aOneRange.aStart.Row() + nRowOffset >= 0 && + aOneRange.aEnd.Row() + nRowOffset <= rDoc.MaxRow() ) + { + ScRange aNew( static_cast<SCCOL>(aOneRange.aStart.Col() + nColumnOffset), + static_cast<SCROW>(aOneRange.aStart.Row() + nRowOffset), + aOneRange.aStart.Tab(), + static_cast<SCCOL>(aOneRange.aEnd.Col() + nColumnOffset), + static_cast<SCROW>(aOneRange.aEnd.Row() + nRowOffset), + aOneRange.aEnd.Tab() ); + SetNewRange( aNew ); + } +} + +// XSheetCellRange + +uno::Reference<sheet::XSpreadsheet> SAL_CALL ScCellCursorObj::getSpreadsheet() +{ + SolarMutexGuard aGuard; + return ScCellRangeObj::getSpreadsheet(); +} + +// XCellRange + +uno::Reference<table::XCell> SAL_CALL ScCellCursorObj::getCellByPosition( + sal_Int32 nColumn, sal_Int32 nRow ) +{ + SolarMutexGuard aGuard; + return ScCellRangeObj::getCellByPosition(nColumn,nRow); +} + +uno::Reference<table::XCellRange> SAL_CALL ScCellCursorObj::getCellRangeByPosition( + sal_Int32 nLeft, sal_Int32 nTop, sal_Int32 nRight, sal_Int32 nBottom ) +{ + SolarMutexGuard aGuard; + return ScCellRangeObj::getCellRangeByPosition(nLeft,nTop,nRight,nBottom); +} + +uno::Reference<table::XCellRange> SAL_CALL ScCellCursorObj::getCellRangeByName( + const OUString& rRange ) +{ + SolarMutexGuard aGuard; + return ScCellRangeObj::getCellRangeByName(rRange); +} + +// XServiceInfo + +OUString SAL_CALL ScCellCursorObj::getImplementationName() +{ + return "ScCellCursorObj"; +} + +sal_Bool SAL_CALL ScCellCursorObj::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +uno::Sequence<OUString> SAL_CALL ScCellCursorObj::getSupportedServiceNames() +{ + // SheetCellCursor should be first (?) + return comphelper::concatSequences<OUString>( + { SCSHEETCELLCURSOR_SERVICE, SCCELLCURSOR_SERVICE }, + ScCellRangeObj::getSupportedServiceNames()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |