desktop/qa/desktop_lib/test_desktop_lib.cxx | 4 include/sal/log-areas.dox | 3 sc/inc/address.hxx | 2 sc/sdi/scalc.sdi | 2 sc/source/ui/inc/tabview.hxx | 5 sc/source/ui/inc/viewdata.hxx | 53 +++ sc/source/ui/unoobj/docuno.cxx | 20 + sc/source/ui/view/cellsh3.cxx | 2 sc/source/ui/view/gridwin.cxx | 7 sc/source/ui/view/tabview.cxx | 426 +++++++++++++++++++++------- sc/source/ui/view/viewdata.cxx | 269 +++++++++++++++++ sc/source/ui/view/viewfunc.cxx | 29 + 12 files changed, 706 insertions(+), 116 deletions(-)
New commits: commit 533a283eeda5d2751e49bbdadfdc673fcefb5e77 Author: Marco Cecchetti <marco.cecche...@collabora.com> Date: Sun Apr 2 20:46:41 2017 +0200 LOK - Calc: beyond row 65535 it is not possibile to resize a row The row parameter type was a unsigned short. Change-Id: I2da1a96d60988e8f1efeb49f55032fb84a8b562b diff --git a/sc/sdi/scalc.sdi b/sc/sdi/scalc.sdi index c19e12268024..735e18086e36 100644 --- a/sc/sdi/scalc.sdi +++ b/sc/sdi/scalc.sdi @@ -4461,7 +4461,7 @@ SfxInt32Item Row SID_RANGE_ROW SfxUInt16Item RowHeight FID_ROW_HEIGHT -(SfxUInt16Item Row FN_PARAM_1,SfxUInt16Item Height FN_PARAM_2) +(SfxInt32Item Row FN_PARAM_1,SfxUInt16Item Height FN_PARAM_2) [ AutoUpdate = FALSE, FastCall = FALSE, diff --git a/sc/source/ui/view/cellsh3.cxx b/sc/source/ui/view/cellsh3.cxx index a9f4c2abab38..1674b121996f 100644 --- a/sc/source/ui/view/cellsh3.cxx +++ b/sc/source/ui/view/cellsh3.cxx @@ -546,7 +546,7 @@ void ScCellShell::Execute( SfxRequest& rReq ) pReqArgs->HasItem( FN_PARAM_2, &pHeight ) ) { std::vector<sc::ColRowSpan> aRanges; - SCCOLROW nRow = static_cast<const SfxUInt16Item*>(pRow)->GetValue() - 1; + SCCOLROW nRow = static_cast<const SfxInt32Item*>(pRow)->GetValue() - 1; sal_uInt16 nHeight = static_cast<const SfxUInt16Item*>(pHeight)->GetValue(); ScMarkData& rMark = GetViewData()->GetMarkData(); commit 105ce60b5274c19bf4f359d31bd4ee37698620bc Author: Marco Cecchetti <marco.cecche...@collabora.com> Date: Wed Mar 29 13:57:31 2017 +0200 LOK - Calc: lift row limit to 500k Due to previously intruduced optimizations, it is safe and fast enough to navigate through a 500k rows document. Change-Id: I8055672b58ea3c1e262f6e49d029eb0cf67086b5 diff --git a/sc/inc/address.hxx b/sc/inc/address.hxx index aa5d4f14017b..43cad11ef409 100644 --- a/sc/inc/address.hxx +++ b/sc/inc/address.hxx @@ -71,7 +71,7 @@ const SCCOL MAXCOL = MAXCOLCOUNT - 1; const SCTAB MAXTAB = MAXTABCOUNT - 1; const SCCOLROW MAXCOLROW = MAXROW; // Maximun tiled rendering values -const SCROW MAXTILEDROW = 10000; +const SCROW MAXTILEDROW = 500000; // Limit the initial tab count to prevent users to set the count too high, // which could cause the memory usage of blank documents to exceed the // available system memory. commit f675f9531483cb59d34c13f3746010e438298704 Author: Marco Cecchetti <marco.cecche...@collabora.com> Date: Wed Mar 29 13:50:18 2017 +0200 LOK - Calc: row/column headers are updated faster Now the computation of the row/column headers data exploits the cached row/col positions in HeightHelper/WidthHelper. That makes updating row/column headers at the bottom of the document as fast as at the top even for very big spreadsheets. Change-Id: Ida0ed8d8885b71fe3206efbdaa62a0bb95153ed7 diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx b/desktop/qa/desktop_lib/test_desktop_lib.cxx index 20958267a291..2dfb036e6be7 100644 --- a/desktop/qa/desktop_lib/test_desktop_lib.cxx +++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx @@ -636,7 +636,7 @@ void DesktopLOKTest::testRowColumnHeaders() if (bFirstHeader) { CPPUNIT_ASSERT(nSize <= nY); - CPPUNIT_ASSERT_EQUAL(OString("11"), aText); + CPPUNIT_ASSERT_EQUAL(OString("10"), aText); bFirstHeader = false; } else @@ -663,7 +663,7 @@ void DesktopLOKTest::testRowColumnHeaders() if (bFirstHeader) { CPPUNIT_ASSERT(nSize <= nX); - CPPUNIT_ASSERT_EQUAL(OString("4"), aText); + CPPUNIT_ASSERT_EQUAL(OString("3"), aText); bFirstHeader = false; } else diff --git a/include/sal/log-areas.dox b/include/sal/log-areas.dox index b702c3ca2324..e51c82c14970 100644 --- a/include/sal/log-areas.dox +++ b/include/sal/log-areas.dox @@ -127,6 +127,7 @@ certain functionality. @li @c sc.core.grouparealistener - sc::FormulaGroupAreaListener @li @c sc.filter - Calc filter @li @c sc.lok.docsize +@li @c sc.lok.header @li @c sc.lok.poshelper @li @c sc.opencl - OpenCL-related stuff in general @li @c sc.opencl.source - Generated OpenCL source code diff --git a/sc/source/ui/inc/tabview.hxx b/sc/source/ui/inc/tabview.hxx index 76643e101be5..076f53f05d4a 100644 --- a/sc/source/ui/inc/tabview.hxx +++ b/sc/source/ui/inc/tabview.hxx @@ -195,6 +195,11 @@ private: double mfPendingTabBarWidth; // Tab bar width relative to frame window width. + SCROW mnLOKStartHeaderRow; + SCROW mnLOKEndHeaderRow; + SCCOL mnLOKStartHeaderCol; + SCCOL mnLOKEndHeaderCol; + bool bMinimized:1; bool bInUpdateHeader:1; bool bInActivatePart:1; diff --git a/sc/source/ui/view/tabview.cxx b/sc/source/ui/view/tabview.cxx index 6e32e84aa9ac..de98051ff3c5 100644 --- a/sc/source/ui/view/tabview.cxx +++ b/sc/source/ui/view/tabview.cxx @@ -227,6 +227,8 @@ ScTabView::ScTabView( vcl::Window* pParent, ScDocShell& rDocSh, ScTabViewShell* nOldCurX( 0 ), nOldCurY( 0 ), mfPendingTabBarWidth( -1.0 ), + mnLOKStartHeaderRow( std::numeric_limits<SCROW>::min() ), + mnLOKEndHeaderRow( std::numeric_limits<SCROW>::min() ), bMinimized( false ), bInUpdateHeader( false ), bInActivatePart( false ), @@ -2305,6 +2307,259 @@ void ScTabView::SetAutoSpellData( SCCOL nPosX, SCROW nPosY, const std::vector<ed } } +namespace +{ + +inline +long lcl_GetRowHeightPx(ScDocument* pDoc, SCROW nRow, SCTAB nTab) +{ + const sal_uInt16 nSize = pDoc->GetRowHeight(nRow, nTab); + return ScViewData::ToPixel(nSize, 1.0 / TWIPS_PER_PIXEL); +} + +inline +long lcl_GetColWidthPx(ScDocument* pDoc, SCCOL nCol, SCTAB nTab) +{ + const sal_uInt16 nSize = pDoc->GetColWidth(nCol, nTab); + return ScViewData::ToPixel(nSize, 1.0 / TWIPS_PER_PIXEL); +} + +} // anonymous namespace + +template<typename IndexType> +class BoundsProvider +{ + typedef ScPositionHelper::value_type value_type; + typedef IndexType index_type; + + static const index_type MAX_INDEX; + + ScDocument* pDoc; + const SCTAB nTab; + + index_type nFirstIndex; + index_type nSecondIndex; + long nFirstPositionPx; + long nSecondPositionPx; + +public: + BoundsProvider(ScDocument* pD, SCTAB nT) + : pDoc(pD) + , nTab(nT) + {} + + void GetStartIndexAndPosition(index_type& nIndex, long& nPosition) const + { + nIndex = nFirstIndex; + nPosition = nFirstPositionPx; + } + + void GetEndIndexAndPosition(index_type& nIndex, long& nPosition) const + { + nIndex = nSecondIndex; + nPosition = nSecondPositionPx; + } + + void Compute(value_type aFirstNearest, value_type aSecondNearest, + long nFirstBound, long nSecondBound); + + void EnlargeStartBy(long nOffset); + + void EnlargeEndBy(long nOffset); + + void EnlargeBy(long nOffset) + { + EnlargeStartBy(nOffset); + EnlargeEndBy(nOffset); + } + +private: + long GetSize(SCROW nIndex) const + { + return lcl_GetRowHeightPx(pDoc, nIndex, nTab); + } + + long GetSize(SCCOL nIndex) const + { + return lcl_GetColWidthPx(pDoc, nIndex, nTab); + } + + void GetIndexAndPos(index_type nNearestIndex, long nNearestPosition, + long nBound, index_type& nFoundIndex, long& nPosition, + bool bTowards, long nDiff) + { + if (nDiff > 0) // nBound < nNearestPosition + GeIndexBackwards(nNearestIndex, nNearestPosition, nBound, + nFoundIndex, nPosition, bTowards); + else + GetIndexTowards(nNearestIndex, nNearestPosition, nBound, + nFoundIndex, nPosition, bTowards); + } + + void GeIndexBackwards(index_type nNearestIndex, long nNearestPosition, + long nBound, index_type& nFoundIndex, long& nPosition, + bool bTowards); + + void GetIndexTowards(index_type nNearestIndex, long nNearestPosition, + long nBound, index_type& nFoundIndex, long& nPosition, + bool bTowards); +}; + +template<typename IndexType> +const IndexType BoundsProvider<IndexType>::MAX_INDEX; + +template<> +const SCROW BoundsProvider<SCROW>::MAX_INDEX = MAXTILEDROW; + +template<> +const SCCOL BoundsProvider<SCCOL>::MAX_INDEX = MAXCOL; + +template<typename IndexType> +void BoundsProvider<IndexType>::Compute( + value_type aFirstNearest, value_type aSecondNearest, + long nFirstBound, long nSecondBound) +{ + SAL_INFO("sc.lok.header", "BoundsProvider: nFirstBound: " << nFirstBound + << ", nSecondBound: " << nSecondBound); + + long nFirstDiff = aFirstNearest.second - nFirstBound; + long nSecondDiff = aSecondNearest.second - nSecondBound; + SAL_INFO("sc.lok.header", "BoundsProvider: rTopNearest: index: " << aFirstNearest.first + << ", pos: " << aFirstNearest.second << ", diff: " << nFirstDiff); + SAL_INFO("sc.lok.header", "BoundsProvider: rBottomNearest: index: " << aSecondNearest.first + << ", pos: " << aSecondNearest.second << ", diff: " << nSecondDiff); + + bool bReverse = !(std::abs(nFirstDiff) < std::abs(nSecondDiff)); + + if(bReverse) + { + std::swap(aFirstNearest, aSecondNearest); + std::swap(nFirstBound, nSecondBound); + std::swap(nFirstDiff, nSecondDiff); + } + + index_type nNearestIndex = aFirstNearest.first; + long nNearestPosition = aFirstNearest.second; + SAL_INFO("sc.lok.header", "BoundsProvider: nearest to first bound: nNearestIndex: " + << nNearestIndex << ", nNearestPosition: " << nNearestPosition); + + GetIndexAndPos(nNearestIndex, nNearestPosition, nFirstBound, + nFirstIndex, nFirstPositionPx, !bReverse, nFirstDiff); + SAL_INFO("sc.lok.header", "BoundsProvider: nFirstIndex: " << nFirstIndex + << ", nFirstPositionPx: " << nFirstPositionPx); + + if (std::abs(nSecondDiff) < std::abs(nSecondBound - nFirstPositionPx)) + { + nNearestIndex = aSecondNearest.first; + nNearestPosition = aSecondNearest.second; + } + else + { + nNearestPosition = nFirstPositionPx; + nNearestIndex = nFirstIndex; + nSecondDiff = !bReverse ? -1 : 1; + } + SAL_INFO("sc.lok.header", "BoundsProvider: nearest to second bound: nNearestIndex: " + << nNearestIndex << ", nNearestPosition: " << nNearestPosition + << ", diff: " << nSecondDiff); + + GetIndexAndPos(nNearestIndex, nNearestPosition, nSecondBound, + nSecondIndex, nSecondPositionPx, bReverse, nSecondDiff); + SAL_INFO("sc.lok.header", "BoundsProvider: nSecondIndex: " << nSecondIndex + << ", nSecondPositionPx: " << nSecondPositionPx); + + if (bReverse) + { + std::swap(nFirstIndex, nSecondIndex); + std::swap(nFirstPositionPx, nSecondPositionPx); + } +} + +template<typename IndexType> +void BoundsProvider<IndexType>::EnlargeStartBy(long nOffset) +{ + const index_type nNewFirstIndex = + std::max(static_cast<index_type>(-1), + static_cast<index_type>(nFirstIndex - nOffset)); + for (index_type nIndex = nFirstIndex; nIndex > nNewFirstIndex; --nIndex) + { + const long nSizePx = GetSize(nIndex); + nFirstPositionPx -= nSizePx; + } + nFirstIndex = nNewFirstIndex; + SAL_INFO("sc.lok.header", "BoundsProvider: added offset: nFirstIndex: " << nFirstIndex + << ", nFirstPositionPx: " << nFirstPositionPx); +} + +template<typename IndexType> +void BoundsProvider<IndexType>::EnlargeEndBy(long nOffset) +{ + const index_type nNewSecondIndex = std::min(MAX_INDEX, static_cast<index_type>(nSecondIndex + nOffset)); + for (index_type nIndex = nSecondIndex + 1; nIndex <= nNewSecondIndex; ++nIndex) + { + const long nSizePx = GetSize(nIndex); + nSecondPositionPx += nSizePx; + } + nSecondIndex = nNewSecondIndex; + SAL_INFO("sc.lok.header", "BoundsProvider: added offset: nSecondIndex: " << nSecondIndex + << ", nSecondPositionPx: " << nSecondPositionPx); +} + +template<typename IndexType> +void BoundsProvider<IndexType>::GeIndexBackwards( + index_type nNearestIndex, long nNearestPosition, + long nBound, index_type& nFoundIndex, long& nPosition, bool bTowards) +{ + nFoundIndex = -1; + for (index_type nIndex = nNearestIndex; nIndex >= 0; --nIndex) + { + if (nBound > nNearestPosition) + { + nFoundIndex = nIndex; // last index whose nPosition is less than nBound + nPosition = nNearestPosition; + break; + } + + const long nSizePx = GetSize(nIndex); + nNearestPosition -= nSizePx; + } + if (!bTowards && nFoundIndex != -1) + { + nFoundIndex += 1; + nPosition += GetSize(nFoundIndex); + } +} + +template<typename IndexType> +void BoundsProvider<IndexType>::GetIndexTowards( + index_type nNearestIndex, long nNearestPosition, + long nBound, index_type& nFoundIndex, long& nPosition, bool bTowards) +{ + nFoundIndex = -2; + for (index_type nIndex = nNearestIndex + 1; nIndex <= MAX_INDEX; ++nIndex) + { + const long nSizePx = GetSize(nIndex); + nNearestPosition += nSizePx; + + if (nNearestPosition > nBound) + { + nFoundIndex = nIndex; // first index whose nPosition is greater than nBound + nPosition = nNearestPosition; + break; + } + } + if (nFoundIndex == -2) + { + nFoundIndex = MAX_INDEX; + nPosition = nNearestPosition; + } + else if (bTowards) + { + nPosition -= GetSize(nFoundIndex); + nFoundIndex -= 1; + } +} + OUString ScTabView::getRowColumnHeaders(const Rectangle& rRectangle) { ScDocument* pDoc = aViewData.GetDocument(); @@ -2317,55 +2572,51 @@ OUString ScTabView::getRowColumnHeaders(const Rectangle& rRectangle) rtl::OUStringBuffer aBuffer(256); aBuffer.append("{ \"commandName\": \".uno:ViewRowColumnHeaders\",\n"); - SCROW nStartRow = 0; - SCROW nEndRow = 0; - SCCOL nStartCol = 0; - SCCOL nEndCol = 0; + SCTAB nTab = aViewData.GetTabNo(); + SCROW nStartRow = -1; + SCROW nEndRow = -1; + long nStartHeightPx = 0; + long nEndHeightPx = 0; + SCCOL nStartCol = -1; + SCCOL nEndCol = -1; + long nStartWidthPx = 0; + long nEndWidthPx = 0; + /// *** start collecting ROWS *** /// 1) compute start and end rows - long nTotalPixels = 0; if (rRectangle.Top() < rRectangle.Bottom()) { - long nUpperBoundPx = rRectangle.Top() / TWIPS_PER_PIXEL; - long nLowerBoundPx = rRectangle.Bottom() / TWIPS_PER_PIXEL; - nEndRow = MAXTILEDROW; - for (SCROW nRow = 0; nRow <= MAXTILEDROW; ++nRow) - { - if (nTotalPixels > nLowerBoundPx) - { - nEndRow = nRow; // first row below the rectangle - break; - } + SAL_INFO("sc.lok.header", "Row Header: compute start/end rows."); + long nRectTopPx = rRectangle.Top() / TWIPS_PER_PIXEL; + long nRectBottomPx = rRectangle.Bottom() / TWIPS_PER_PIXEL; - const sal_uInt16 nSize = pDoc->GetRowHeight(nRow, aViewData.GetTabNo()); - const long nSizePx = ScViewData::ToPixel(nSize, 1.0 / TWIPS_PER_PIXEL); + const auto& rTopNearest = aViewData.GetLOKHeightHelper().getNearestByPosition(nRectTopPx); + const auto& rBottomNearest = aViewData.GetLOKHeightHelper().getNearestByPosition(nRectBottomPx); - nTotalPixels += nSizePx; - - if (nTotalPixels < nUpperBoundPx) - { - nStartRow = nRow; // last row above the rectangle - continue; - } - } + BoundsProvider<SCROW> aBoundingRowsProvider(pDoc, nTab); + aBoundingRowsProvider.Compute(rTopNearest, rBottomNearest, nRectTopPx, nRectBottomPx); + aBoundingRowsProvider.EnlargeBy(2); + aBoundingRowsProvider.GetStartIndexAndPosition(nStartRow, nStartHeightPx); + aBoundingRowsProvider.GetEndIndexAndPosition(nEndRow, nEndHeightPx); - nStartRow -= 1; - nEndRow += 2; + aViewData.GetLOKHeightHelper().removeByIndex(mnLOKStartHeaderRow); + aViewData.GetLOKHeightHelper().removeByIndex(mnLOKEndHeaderRow); + aViewData.GetLOKHeightHelper().insert(nStartRow, nStartHeightPx); + aViewData.GetLOKHeightHelper().insert(nEndRow, nEndHeightPx); - if (nStartRow < 0) nStartRow = 0; - if (nEndRow > MAXTILEDROW) nEndRow = MAXTILEDROW; + mnLOKStartHeaderRow = nStartRow; + mnLOKEndHeaderRow = nEndRow; } - aBuffer.ensureCapacity( aBuffer.getCapacity() + (50 * (nEndRow - nStartRow + 1)) ); - - long nVisibleRows = nEndRow - nStartRow; if (nVisibleRows < 25) nVisibleRows = 25; + SAL_INFO("sc.lok.header", "Row Header: visible rows: " << nVisibleRows); + /// 2) if we are approaching current max tiled row, signal a size changed event /// and invalidate the involved area @@ -2384,6 +2635,7 @@ OUString ScTabView::getRowColumnHeaders(const Rectangle& rRectangle) if (pModelObj) aNewSize = pModelObj->getDocumentSize(); + SAL_INFO("sc.lok.header", "Row Header: a new height: " << aNewSize.Height()); if (pDocSh) { // Provide size in the payload, so clients don't have to @@ -2410,39 +2662,27 @@ OUString ScTabView::getRowColumnHeaders(const Rectangle& rRectangle) aBuffer.append("\"rows\": [\n"); - bool bFirstRow = true; - if (nStartRow == 0 && nStartRow != nEndRow) + long nTotalPixels = aViewData.GetLOKHeightHelper().getPosition(nStartRow); + SAL_INFO("sc.lok.header", "Row Header: [create string data for rows]: start row: " + << nStartRow << " start height: " << nTotalPixels); + + if (nStartRow != nEndRow) { - aBuffer.append("{ \"text\": \"").append("0").append("\", "); - aBuffer.append("\"size\": \"").append(OUString::number(0)).append("\" }"); - bFirstRow = false; + OUString aText = OUString::number(nStartRow + 1); + aBuffer.append("{ \"text\": \"").append(aText).append("\", "); + aBuffer.append("\"size\": \"").append(OUString::number(nTotalPixels * TWIPS_PER_PIXEL)).append("\" }"); } - nTotalPixels = 0; - for (SCROW nRow = 0; nRow < nEndRow; ++nRow) + for (SCROW nRow = nStartRow + 1; nRow < nEndRow; ++nRow) { // nSize will be 0 for hidden rows. - const sal_uInt16 nSize = pDoc->GetRowHeight(nRow, aViewData.GetTabNo()); - const long nSizePx = ScViewData::ToPixel(nSize, 1.0 / TWIPS_PER_PIXEL); + const long nSizePx = lcl_GetRowHeightPx(pDoc, nRow, nTab); nTotalPixels += nSizePx; - if (nRow < nStartRow) - continue; - OUString aText = pRowBar[SC_SPLIT_BOTTOM]->GetEntryText(nRow); - - if (!bFirstRow) - { - aBuffer.append(", "); - } - else - { - aText = OUString::number(nStartRow + 1); - } - + aBuffer.append(", "); aBuffer.append("{ \"text\": \"").append(aText).append("\", "); aBuffer.append("\"size\": \"").append(OUString::number(nTotalPixels * TWIPS_PER_PIXEL)).append("\" }"); - bFirstRow = false; } aBuffer.append("]"); @@ -2455,35 +2695,28 @@ OUString ScTabView::getRowColumnHeaders(const Rectangle& rRectangle) /// 1) compute start and end columns - nTotalPixels = 0; if (rRectangle.Left() < rRectangle.Right()) { - long nLeftBoundPx = rRectangle.Left() / TWIPS_PER_PIXEL; - long nRightBoundPx = rRectangle.Right() / TWIPS_PER_PIXEL; - nEndCol = MAXCOL; - for (SCCOL nCol = 0; nCol <= MAXCOL; ++nCol) - { - if (nTotalPixels > nRightBoundPx) - { - nEndCol = nCol; - break; - } + SAL_INFO("sc.lok.header", "Column Header: compute start/end columns."); + long nRectLeftPx = rRectangle.Left() / TWIPS_PER_PIXEL; + long nRectRightPx = rRectangle.Right() / TWIPS_PER_PIXEL; - const sal_uInt16 nSize = pDoc->GetColWidth(nCol, aViewData.GetTabNo()); - const long nSizePx = ScViewData::ToPixel(nSize, 1.0 / TWIPS_PER_PIXEL); - nTotalPixels += nSizePx; - if (nTotalPixels < nLeftBoundPx) - { - nStartCol = nCol; - continue; - } - } + const auto& rLeftNearest = aViewData.GetLOKWidthHelper().getNearestByPosition(nRectLeftPx); + const auto& rRightNearest = aViewData.GetLOKWidthHelper().getNearestByPosition(nRectRightPx); + + BoundsProvider<SCCOL> aBoundingColsProvider(pDoc, nTab); + aBoundingColsProvider.Compute(rLeftNearest, rRightNearest, nRectLeftPx, nRectRightPx); + aBoundingColsProvider.EnlargeBy(2); + aBoundingColsProvider.GetStartIndexAndPosition(nStartCol, nStartWidthPx); + aBoundingColsProvider.GetEndIndexAndPosition(nEndCol, nEndWidthPx); - nStartCol -= 1; - nEndCol += 2; + aViewData.GetLOKWidthHelper().removeByIndex(mnLOKStartHeaderCol); + aViewData.GetLOKWidthHelper().removeByIndex(mnLOKEndHeaderCol); + aViewData.GetLOKWidthHelper().insert(nStartCol, nStartWidthPx); + aViewData.GetLOKWidthHelper().insert(nEndCol, nEndWidthPx); - if (nStartCol < 0) nStartCol = 0; - if (nEndCol > MAXCOL) nEndCol = MAXCOL; + mnLOKStartHeaderCol = nStartCol; + mnLOKEndHeaderCol = nEndCol; } aBuffer.ensureCapacity( aBuffer.getCapacity() + (50 * (nEndCol - nStartCol + 1)) ); @@ -2531,44 +2764,31 @@ OUString ScTabView::getRowColumnHeaders(const Rectangle& rRectangle) } } - /// 3) create string data for columns aBuffer.append("\"columns\": [\n"); - bool bFirstCol = true; - if (nStartCol == 0 && nStartCol != nEndCol ) + nTotalPixels = aViewData.GetLOKWidthHelper().getPosition(nStartCol); + SAL_INFO("sc.lok.header", "Col Header: [create string data for cols]: start col: " + << nStartRow << " start width: " << nTotalPixels); + + if (nStartCol != nEndCol) { - aBuffer.append("{ \"text\": \"").append("0").append("\", "); - aBuffer.append("\"size\": \"").append(OUString::number(0)).append("\" }"); - bFirstCol = false; + OUString aText = OUString::number(nStartCol + 1); + aBuffer.append("{ \"text\": \"").append(aText).append("\", "); + aBuffer.append("\"size\": \"").append(OUString::number(nTotalPixels * TWIPS_PER_PIXEL)).append("\" }"); } - nTotalPixels = 0; - for (SCCOL nCol = 0; nCol < nEndCol; ++nCol) + for (SCCOL nCol = nStartCol + 1; nCol < nEndCol; ++nCol) { // nSize will be 0 for hidden columns. - const sal_uInt16 nSize = pDoc->GetColWidth(nCol, aViewData.GetTabNo()); - const long nSizePx = ScViewData::ToPixel(nSize, 1.0 / TWIPS_PER_PIXEL); + const long nSizePx = lcl_GetColWidthPx(pDoc, nCol, nTab); nTotalPixels += nSizePx; - if (nCol < nStartCol) - continue; - OUString aText = pColBar[SC_SPLIT_LEFT]->GetEntryText(nCol); - - if (!bFirstCol) - { - aBuffer.append(", "); - } - else - { - aText = OUString::number(nStartCol + 1); - } - + aBuffer.append(", "); aBuffer.append("{ \"text\": \"").append(aText).append("\", "); aBuffer.append("\"size\": \"").append(OUString::number(nTotalPixels * TWIPS_PER_PIXEL)).append("\" }"); - bFirstCol = false; } aBuffer.append("]"); commit 4b39183c5740067cc31c006214cb24b81ee0f98c Author: Marco Cecchetti <marco.cecche...@collabora.com> Date: Wed Mar 29 13:42:35 2017 +0200 LOK - Calc: make computation of cell cursor position faster Now the computation of the cell cursor position exploits the cached row/col positions in HeightHelper/WidthHelper. That makes navigating through arrow keys independent from the current cell cursor position: the cell cursor position is updated at the bottom of the document as fast as at the top even for very big spreadsheets. Change-Id: Id369b63e547aedf30c233f75c70d18f32e015edf diff --git a/sc/source/ui/inc/viewdata.hxx b/sc/source/ui/inc/viewdata.hxx index af6786b69361..06d829613c0d 100644 --- a/sc/source/ui/inc/viewdata.hxx +++ b/sc/source/ui/inc/viewdata.hxx @@ -177,6 +177,9 @@ private: SCROW nCurY; SCCOL nOldCurX; SCROW nOldCurY; + SCCOL nLOKOldCurX; + SCROW nLOKOldCurY; + ScPositionHelper aWidthHelper; ScPositionHelper aHeightHelper; @@ -332,6 +335,8 @@ public: SCROW GetCurY() const { return pThisTab->nCurY; } SCCOL GetOldCurX() const; SCROW GetOldCurY() const; + SCCOL GetLOKOldCurX() const { return pThisTab->nLOKOldCurX; } + SCROW GetLOKOldCurY() const { return pThisTab->nLOKOldCurY; } long GetLOKDocWidthPixel() const { return pThisTab->aWidthHelper.getPosition(pThisTab->nMaxTiledCol); } long GetLOKDocHeightPixel() const { return pThisTab->aHeightHelper.getPosition(pThisTab->nMaxTiledRow); } @@ -357,6 +362,9 @@ public: void SetCurY( SCROW nNewCurY ) { pThisTab->nCurY = nNewCurY; } void SetOldCursor( SCCOL nNewX, SCROW nNewY ); void ResetOldCursor(); + void SetLOKOldCurX( SCCOL nCurX ) { pThisTab->nLOKOldCurX = nCurX; } + void SetLOKOldCurY( SCROW nCurY ) { pThisTab->nLOKOldCurY = nCurY; } + void SetHSplitMode( ScSplitMode eMode ) { pThisTab->eHSplitMode = eMode; } void SetVSplitMode( ScSplitMode eMode ) { pThisTab->eVSplitMode = eMode; } void SetHSplitPos( long nPos ) { pThisTab->nHSplitPos = nPos; } diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx index d2b8f97a1d21..6610d616a28b 100644 --- a/sc/source/ui/view/gridwin.cxx +++ b/sc/source/ui/view/gridwin.cxx @@ -5741,6 +5741,13 @@ OString ScGridWindow::getCellCursor(const Fraction& rZoomX, const Fraction& rZoo pViewData->SetZoom(defaultZoomX, defaultZoomY, true); + pViewData->GetLOKWidthHelper().removeByIndex(pViewData->GetLOKOldCurX() - 1); + pViewData->GetLOKWidthHelper().insert(nX - 1, aScrPos.getX()); + pViewData->SetLOKOldCurX(nX); + pViewData->GetLOKHeightHelper().removeByIndex(pViewData->GetLOKOldCurY() - 1); + pViewData->GetLOKHeightHelper().insert(nY - 1, aScrPos.getY()); + pViewData->SetLOKOldCurY(nY); + return aRect.toString(); } diff --git a/sc/source/ui/view/viewdata.cxx b/sc/source/ui/view/viewdata.cxx index dbfd41492601..fb71e4c47c01 100644 --- a/sc/source/ui/view/viewdata.cxx +++ b/sc/source/ui/view/viewdata.cxx @@ -268,6 +268,8 @@ ScViewDataTable::ScViewDataTable() : nCurY( 0 ), nOldCurX( 0 ), nOldCurY( 0 ), + nLOKOldCurX( 0 ), + nLOKOldCurY( 0 ), nMaxTiledCol( 20 ), nMaxTiledRow( 50 ), bShowGrid( true ), @@ -1881,6 +1883,13 @@ Point ScViewData::GetScrPos( SCCOL nWhereX, SCROW nWhereY, ScSplitPos eWhich, SCCOL nX; long nScrPosX=0; + if (bIsTiledRendering) + { + const auto& rNearest = pThisTab->aWidthHelper.getNearestByIndex(nWhereX - 1); + nPosX = rNearest.first + 1; + nScrPosX = rNearest.second; + } + if (nWhereX >= nPosX) for (nX = nPosX; nX < nWhereX && (bAllowNeg || bIsTiledRendering || nScrPosX <= aScrSize.Width()); nX++) { @@ -1912,6 +1921,13 @@ Point ScViewData::GetScrPos( SCCOL nWhereX, SCROW nWhereY, ScSplitPos eWhich, SCROW nY; long nScrPosY=0; + if (bIsTiledRendering) + { + const auto& rNearest = pThisTab->aHeightHelper.getNearestByIndex(nWhereY - 1); + nPosY = rNearest.first + 1; + nScrPosY = rNearest.second; + } + if (nWhereY >= nPosY) for (nY = nPosY; nY < nWhereY && (bAllowNeg || bIsTiledRendering || nScrPosY <= aScrSize.Height()); nY++) { commit 45694a63614396a98ac56deaf9f548576ae7b95e Author: Marco Cecchetti <marco.cecche...@collabora.com> Date: Wed Mar 29 13:17:43 2017 +0200 LOK - Calc: invalidation of cached row/col positions on several cases Cached row positions are invalidated when one of the following event occurs: - one or more rows are inserted - one or more rows are deleted - one or more hidden rows are made visible - one or more visible rows are made hidden - one row is resized - optimal row height is changed - the value of the PPTY parameter is updated The same occurs for cached column positions. Change-Id: Idf7b8cf1e694142e4fa0e1613d19ee9272b9a1be diff --git a/sc/source/ui/view/viewdata.cxx b/sc/source/ui/view/viewdata.cxx index 473bf6736f03..dbfd41492601 100644 --- a/sc/source/ui/view/viewdata.cxx +++ b/sc/source/ui/view/viewdata.cxx @@ -2502,6 +2502,8 @@ void ScViewData::UpdateScreenZoom( const Fraction& rNewX, const Fraction& rNewY void ScViewData::CalcPPT() { + double nOldPPTX = nPPTX; + double nOldPPTY = nPPTY; nPPTX = ScGlobal::nScreenPPTX * (double) GetZoomX(); if (pDocShell) nPPTX = nPPTX / pDocShell->GetOutputFactor(); // Factor is printer to screen @@ -2538,6 +2540,11 @@ void ScViewData::CalcPPT() } } } + + if (nPPTX != nOldPPTX) + GetLOKWidthHelper().invalidateByPosition(0L); + if (nPPTY != nOldPPTY) + GetLOKHeightHelper().invalidateByPosition(0L); } #define SC_OLD_TABSEP '/' diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx index 0228541fe286..6ad62019050b 100644 --- a/sc/source/ui/view/viewfunc.cxx +++ b/sc/source/ui/view/viewfunc.cxx @@ -77,6 +77,7 @@ #include "tokenarray.hxx" #include <rowheightcontext.hxx> #include <docfuncutil.hxx> +#include <comphelper/lok.hxx> #include <memory> @@ -1457,13 +1458,23 @@ bool ScViewFunc::InsertCells( InsCellCmd eCmd, bool bRecord, bool bPartOfPaste ) bool bSuccess = pDocSh->GetDocFunc().InsertCells( aRange, &rMark, eCmd, bRecord, false, bPartOfPaste ); if (bSuccess) { + bool bInsertCols = ( eCmd == INS_INSCOLS_BEFORE || eCmd == INS_INSCOLS_AFTER); + bool bInsertRows = ( eCmd == INS_INSROWS_BEFORE || eCmd == INS_INSROWS_AFTER ); + if (comphelper::LibreOfficeKit::isActive()) + { + if (bInsertCols) + GetViewData().GetLOKWidthHelper().invalidateByIndex(aRange.aStart.Col()); + + if (bInsertRows) + GetViewData().GetLOKHeightHelper().invalidateByIndex(aRange.aStart.Row()); + } pDocSh->UpdateOle(&GetViewData()); CellContentChanged(); ResetAutoSpell(); - if ( eCmd == INS_INSROWS_BEFORE || eCmd == INS_INSCOLS_BEFORE || eCmd == INS_INSROWS_AFTER || eCmd == INS_INSCOLS_AFTER ) + if ( bInsertRows || bInsertCols ) { - OUString aOperation = ( eCmd == INS_INSROWS_BEFORE || eCmd == INS_INSROWS_AFTER ) ? + OUString aOperation = bInsertRows ? OUString("insert-rows"): OUString("insert-columns"); HelperNotifyChanges::NotifyIfChangesListeners(*pDocSh, aRange, aOperation); @@ -1514,6 +1525,15 @@ void ScViewFunc::DeleteCells( DelCellCmd eCmd ) pDocSh->GetDocFunc().DeleteCells( aRange, &rMark, eCmd, false ); } + if (comphelper::LibreOfficeKit::isActive()) + { + if (eCmd == DEL_DELCOLS) + GetViewData().GetLOKWidthHelper().invalidateByIndex(aRange.aStart.Col()); + + if (eCmd == DEL_DELROWS) + GetViewData().GetLOKHeightHelper().invalidateByIndex(aRange.aStart.Row()); + } + pDocSh->UpdateOle(&GetViewData()); CellContentChanged(); ResetAutoSpell(); @@ -1874,6 +1894,11 @@ void ScViewFunc::SetWidthOrHeight( SCCOLROW nStart = rRanges.front().mnStart; SCCOLROW nEnd = rRanges.back().mnEnd; + if (bWidth) + GetViewData().GetLOKWidthHelper().invalidateByIndex(nStart); + else + GetViewData().GetLOKHeightHelper().invalidateByIndex(nStart); + bool bFormula = false; if ( eMode == SC_SIZE_OPTIMAL ) { commit 5894e6bfe6ee403373b6b8775282a7b48a5e4932 Author: Marco Cecchetti <marco.cecche...@collabora.com> Date: Wed Mar 29 12:55:12 2017 +0200 LOK - Calc: document size as sum of row heights/col widths in pixel Grid lines, cursor overlay, row/col headers are all computed by summing up row heights / col widths converted to pixels. On the contrary the document size was converted to pixel only at the end after having summed up heights/widths in twips. All that lead to have a document height/width greater than the position of the last row/col, with the scrolling in online going unplesantly far beyond the last row/column. This patch change the way the document size is computed, so that the spreadsheet height/width matches the position of the last row/column. Moreover it exploits the cache-like structure for row/col positions introduced in a previous commit. Change-Id: I2e7b0e9601653856f88d1e5f9791aaec271592dc diff --git a/include/sal/log-areas.dox b/include/sal/log-areas.dox index aafdf6b5d6a2..b702c3ca2324 100644 --- a/include/sal/log-areas.dox +++ b/include/sal/log-areas.dox @@ -126,6 +126,7 @@ certain functionality. @li @c sc.core.formulagroup @li @c sc.core.grouparealistener - sc::FormulaGroupAreaListener @li @c sc.filter - Calc filter +@li @c sc.lok.docsize @li @c sc.lok.poshelper @li @c sc.opencl - OpenCL-related stuff in general @li @c sc.opencl.source - Generated OpenCL source code diff --git a/sc/source/ui/inc/viewdata.hxx b/sc/source/ui/inc/viewdata.hxx index 33ee723fc533..af6786b69361 100644 --- a/sc/source/ui/inc/viewdata.hxx +++ b/sc/source/ui/inc/viewdata.hxx @@ -332,6 +332,9 @@ public: SCROW GetCurY() const { return pThisTab->nCurY; } SCCOL GetOldCurX() const; SCROW GetOldCurY() const; + long GetLOKDocWidthPixel() const { return pThisTab->aWidthHelper.getPosition(pThisTab->nMaxTiledCol); } + long GetLOKDocHeightPixel() const { return pThisTab->aHeightHelper.getPosition(pThisTab->nMaxTiledRow); } + ScPositionHelper& GetLOKWidthHelper() { return pThisTab->aWidthHelper; } ScPositionHelper& GetLOKHeightHelper() { return pThisTab->aHeightHelper; } @@ -360,8 +363,8 @@ public: void SetVSplitPos( long nPos ) { pThisTab->nVSplitPos = nPos; } void SetFixPosX( SCCOL nPos ) { pThisTab->nFixPosX = nPos; } void SetFixPosY( SCROW nPos ) { pThisTab->nFixPosY = nPos; } - void SetMaxTiledCol( SCCOL nCol ) { pThisTab->nMaxTiledCol = nCol; } - void SetMaxTiledRow( SCROW nRow ) { pThisTab->nMaxTiledRow = nRow; } + void SetMaxTiledCol( SCCOL nCol ); + void SetMaxTiledRow( SCROW nRow ); void SetPagebreakMode( bool bSet ); void SetPasteMode ( ScPasteFlags nFlags ) { nPasteFlags = nFlags; } diff --git a/sc/source/ui/unoobj/docuno.cxx b/sc/source/ui/unoobj/docuno.cxx index 4f3b627a7029..35fa76e8e669 100644 --- a/sc/source/ui/unoobj/docuno.cxx +++ b/sc/source/ui/unoobj/docuno.cxx @@ -544,7 +544,7 @@ Size ScModelObj::getDocumentSize() { Size aSize(10, 10); // minimum size - const ScViewData* pViewData = ScDocShell::GetViewData(); + ScViewData* pViewData = ScDocShell::GetViewData(); if (!pViewData) return aSize; @@ -555,9 +555,21 @@ Size ScModelObj::getDocumentSize() rDoc.GetTiledRenderingArea(nTab, nEndCol, nEndRow); - // convert to twips - aSize.setWidth(rDoc.GetColWidth(0, nEndCol, nTab)); - aSize.setHeight(rDoc.GetRowHeight(0, nEndRow, nTab)); + pViewData->SetMaxTiledCol(nEndCol); + pViewData->SetMaxTiledRow(nEndRow); + + if (pViewData->GetLOKDocWidthPixel() > 0 && pViewData->GetLOKDocHeightPixel() > 0) + { + // convert to twips + aSize.setWidth(pViewData->GetLOKDocWidthPixel() * TWIPS_PER_PIXEL); + aSize.setHeight(pViewData->GetLOKDocHeightPixel() * TWIPS_PER_PIXEL); + } + else + { + // convert to twips + aSize.setWidth(rDoc.GetColWidth(0, nEndCol, nTab)); + aSize.setHeight(rDoc.GetRowHeight(0, nEndRow, nTab)); + } return aSize; } diff --git a/sc/source/ui/view/viewdata.cxx b/sc/source/ui/view/viewdata.cxx index 4b6c8c0ef482..473bf6736f03 100644 --- a/sc/source/ui/view/viewdata.cxx +++ b/sc/source/ui/view/viewdata.cxx @@ -1120,6 +1120,92 @@ void ScViewData::ResetOldCursor() pThisTab->mbOldCursorValid = false; } +void ScViewData::SetMaxTiledCol( SCCOL nNewMaxCol ) +{ + if (nNewMaxCol < 0) + nNewMaxCol = 0; + if (nNewMaxCol > MAXCOL) + nNewMaxCol = MAXCOL; + + const SCTAB nTab = GetTabNo(); + ScDocument* pThisDoc = pDoc; + auto GetColWidthPx = [pThisDoc, nTab](SCCOL nCol) { + const sal_uInt16 nSize = pThisDoc->GetColWidth(nCol, nTab); + const long nSizePx = ScViewData::ToPixel(nSize, 1.0 / TWIPS_PER_PIXEL); + return nSizePx; + }; + + const auto& rNearest = GetLOKWidthHelper().getNearestByIndex(nNewMaxCol); + SCCOL nStartCol = rNearest.first; + long nTotalPixels = rNearest.second; + + if (nStartCol < nNewMaxCol) + { + for (SCCOL nCol = nStartCol + 1; nCol <= nNewMaxCol; ++nCol) + { + nTotalPixels += GetColWidthPx(nCol); + } + } + else + { + for (SCCOL nCol = nStartCol; nCol > nNewMaxCol; --nCol) + { + nTotalPixels -= GetColWidthPx(nCol); + } + } + + SAL_INFO("sc.lok.docsize", "ScViewData::SetMaxTiledCol: nNewMaxCol: " + << nNewMaxCol << ", nTotalPixels: " << nTotalPixels); + + GetLOKWidthHelper().removeByIndex(pThisTab->nMaxTiledCol); + GetLOKWidthHelper().insert(nNewMaxCol, nTotalPixels); + + pThisTab->nMaxTiledCol = nNewMaxCol; +} + +void ScViewData::SetMaxTiledRow( SCROW nNewMaxRow ) +{ + if (nNewMaxRow < 0) + nNewMaxRow = 0; + if (nNewMaxRow > MAXTILEDROW) + nNewMaxRow = MAXTILEDROW; + + const SCTAB nTab = GetTabNo(); + ScDocument* pThisDoc = pDoc; + auto GetRowHeightPx = [pThisDoc, nTab](SCROW nRow) { + const sal_uInt16 nSize = pThisDoc->GetRowHeight(nRow, nTab); + const long nSizePx = ScViewData::ToPixel(nSize, 1.0 / TWIPS_PER_PIXEL); + return nSizePx; + }; + + const auto& rNearest = GetLOKHeightHelper().getNearestByIndex(nNewMaxRow); + SCROW nStartRow = rNearest.first; + long nTotalPixels = rNearest.second; + + if (nStartRow < nNewMaxRow) + { + for (SCROW nRow = nStartRow + 1; nRow <= nNewMaxRow; ++nRow) + { + nTotalPixels += GetRowHeightPx(nRow); + } + } + else + { + for (SCROW nRow = nStartRow; nRow > nNewMaxRow; --nRow) + { + nTotalPixels -= GetRowHeightPx(nRow); + } + } + + SAL_INFO("sc.lok.docsize", "ScViewData::SetMaxTiledRow: nNewMaxRow: " + << nNewMaxRow << ", nTotalPixels: " << nTotalPixels); + + GetLOKHeightHelper().removeByIndex(pThisTab->nMaxTiledRow); + GetLOKHeightHelper().insert(nNewMaxRow, nTotalPixels); + + pThisTab->nMaxTiledRow = nNewMaxRow; +} + Rectangle ScViewData::GetEditArea( ScSplitPos eWhich, SCCOL nPosX, SCROW nPosY, vcl::Window* pWin, const ScPatternAttr* pPattern, bool bForceToTop ) commit 2488f695197fe987951cd6f4f1552ab7c5f22897 Author: Marco Cecchetti <marco.cecche...@collabora.com> Date: Thu Feb 23 19:20:05 2017 +0100 LOK - Calc: a cache-like structure for row/col positions in the document ScPositionHelper provides the ability to insert (and remove) row- position pairs where the position is in pixel and related to the spreadsheet top. In this way one can compute a new row position by starting from the nearest row presents in this cache-like structure. It offers also the ability to invalidate the cache by removing all cached data below a given row or position. This data structure can be used for columns, too. Change-Id: I89c62b81fe9ae685ee84c33a128893c960ebd27e diff --git a/include/sal/log-areas.dox b/include/sal/log-areas.dox index c5cdc3c188db..aafdf6b5d6a2 100644 --- a/include/sal/log-areas.dox +++ b/include/sal/log-areas.dox @@ -126,6 +126,7 @@ certain functionality. @li @c sc.core.formulagroup @li @c sc.core.grouparealistener - sc::FormulaGroupAreaListener @li @c sc.filter - Calc filter +@li @c sc.lok.poshelper @li @c sc.opencl - OpenCL-related stuff in general @li @c sc.opencl.source - Generated OpenCL source code @li @c sc.orcus diff --git a/sc/source/ui/inc/viewdata.hxx b/sc/source/ui/inc/viewdata.hxx index 42b0cbebfe0a..33ee723fc533 100644 --- a/sc/source/ui/inc/viewdata.hxx +++ b/sc/source/ui/inc/viewdata.hxx @@ -115,6 +115,38 @@ class ScViewData; class ScMarkData; class ScGridWindow; +class ScPositionHelper +{ +public: + typedef SCCOLROW index_type; + typedef std::pair<index_type, long> value_type; + static_assert(std::numeric_limits<index_type>::is_signed, "ScPositionCache: index type is not signed"); + +private: + static const index_type null = std::numeric_limits<index_type>::min(); + + class Comp + { + public: + bool operator() (const value_type& rValue1, const value_type& rValue2) const; + }; + + std::set<value_type, Comp> mData; + +public: + ScPositionHelper(); + + void insert(index_type nIndex, long nPos); + void removeByIndex(index_type nIndex); + void removeByPosition(long nPos); + void invalidateByIndex(index_type nIndex); + void invalidateByPosition(long nPos); + const value_type& getNearestByIndex(index_type nIndex) const; + const value_type& getNearestByPosition(long nPos) const; + long getPosition(index_type nIndex) const; + index_type getIndex(long nPos) const; +}; + class ScViewDataTable // per-sheet data { friend class ScViewData; @@ -145,6 +177,9 @@ private: SCROW nCurY; SCCOL nOldCurX; SCROW nOldCurY; + ScPositionHelper aWidthHelper; + ScPositionHelper aHeightHelper; + SCCOL nPosX[2]; ///< X position of the top left cell of the visible area. SCROW nPosY[2]; ///< Y position of the top left cell of the visible area. SCCOL nMaxTiledCol; @@ -297,6 +332,9 @@ public: SCROW GetCurY() const { return pThisTab->nCurY; } SCCOL GetOldCurX() const; SCROW GetOldCurY() const; + ScPositionHelper& GetLOKWidthHelper() { return pThisTab->aWidthHelper; } + ScPositionHelper& GetLOKHeightHelper() { return pThisTab->aHeightHelper; } + ScSplitMode GetHSplitMode() const { return pThisTab->eHSplitMode; } ScSplitMode GetVSplitMode() const { return pThisTab->eVSplitMode; } long GetHSplitPos() const { return pThisTab->nHSplitPos; } diff --git a/sc/source/ui/view/viewdata.cxx b/sc/source/ui/view/viewdata.cxx index c6111917c6ec..4b6c8c0ef482 100644 --- a/sc/source/ui/view/viewdata.cxx +++ b/sc/source/ui/view/viewdata.cxx @@ -91,6 +91,166 @@ void lcl_LOKRemoveWindow(ScTabViewShell* pTabViewShell, ScSplitPos eWhich) } // anonymous namespace +const ScPositionHelper::index_type ScPositionHelper::null; // definition + +bool ScPositionHelper::Comp::operator() (const value_type& rValue1, const value_type& rValue2) const +{ + if (rValue1.first == null || rValue2.first == null) + { + return rValue1.second < rValue2.second; + } + else + { + return rValue1.first < rValue2.first; + } +} + +ScPositionHelper::ScPositionHelper() +{ + mData.insert(std::make_pair(-1, 0)); +} + +void ScPositionHelper::insert(index_type nIndex, long nPos) +{ + if (nIndex < 0) return; + SAL_INFO("sc.lok.poshelper", "ScPositionHelper::insert: nIndex: " + << nIndex << ", nPos: " << nPos << ", size: " << mData.size()); + value_type aValue = std::make_pair(nIndex, nPos); + mData.erase(aValue); + mData.insert(aValue); + SAL_INFO("sc.lok.poshelper", + "ScPositionHelper::insert: after insert: size: " << mData.size()); +} + +void ScPositionHelper::removeByIndex(index_type nIndex) +{ + if (nIndex < 0) + return; + SAL_INFO("sc.lok.poshelper", "ScPositionHelper::remove: nIndex: " << nIndex + << ", size: " << mData.size()); + auto it = mData.find(std::make_pair(nIndex, 0)); + if (it == mData.end()) return; + mData.erase(it); + SAL_INFO("sc.lok.poshelper", + "ScPositionHelper::remove: after erase: size: " << mData.size()); +} + +void ScPositionHelper::removeByPosition(long nPos) +{ + SAL_INFO("sc.lok.poshelper", "ScPositionHelper::remove: nPos: " << nPos + << ", size: " << mData.size()); + auto it = mData.find(std::make_pair(null, nPos)); + if (it == mData.end() || it->first <= 0) + return; + mData.erase(it); + SAL_INFO("sc.lok.poshelper", + "ScPositionHelper::remove: after erase: size: " << mData.size()); +} + +void ScPositionHelper::invalidateByIndex(index_type nIndex) +{ + SAL_INFO("sc.lok.poshelper", "ScPositionHelper::invalidate: nIndex: " << nIndex); + if (nIndex < 0) + { + mData.clear(); + mData.insert(std::make_pair(-1, 0)); + } + else + { + auto it = mData.lower_bound(std::make_pair(nIndex, 0)); + mData.erase(it, mData.end()); + } +} + +void ScPositionHelper::invalidateByPosition(long nPos) +{ + SAL_INFO("sc.lok.poshelper", "ScPositionHelper::invalidate: nPos: " << nPos); + if (nPos <= 0) + { + mData.clear(); + mData.insert(std::make_pair(-1, 0)); + } + else + { + auto it = mData.lower_bound(std::make_pair(null, nPos)); + mData.erase(it, mData.end()); + } +} + +const ScPositionHelper::value_type& +ScPositionHelper::getNearestByIndex(index_type nIndex) const +{ + SAL_INFO("sc.lok.poshelper", + "ScPositionHelper::getNearest: nIndex: " << nIndex << ", size: " << mData.size()); + auto posUB = mData.upper_bound(std::make_pair(nIndex, 0)); + if (posUB == mData.begin()) + { + return *posUB; + } + + auto posLB = std::prev(posUB); + if (posUB == mData.end()) + { + return *posLB; + } + + long nDiffUB = posUB->first - nIndex; + long nDiffLB = posLB->first - nIndex; + if (nDiffUB < -nDiffLB) + { + return *posUB; + } + else + { + return *posLB; + } +} + +const ScPositionHelper::value_type& +ScPositionHelper::getNearestByPosition(long nPos) const +{ + SAL_INFO("sc.lok.poshelper", + "ScPositionHelper::getNearest: nPos: " << nPos << ", size: " << mData.size()); + auto posUB = mData.upper_bound(std::make_pair(null, nPos)); + + if (posUB == mData.begin()) + { + return *posUB; + } + + auto posLB = std::prev(posUB); + if (posUB == mData.end()) + { + return *posLB; + } + + long nDiffUB = posUB->second - nPos; + long nDiffLB = posLB->second - nPos; + + if (nDiffUB < -nDiffLB) + { + return *posUB; + } + else + { + return *posLB; + } +} + +long ScPositionHelper::getPosition(index_type nIndex) const +{ + auto it = mData.find(std::make_pair(nIndex, 0)); + if (it == mData.end()) return -1; + return it->second; +} + +ScPositionHelper::index_type ScPositionHelper::getIndex(long nPos) const +{ + auto it = mData.find(std::make_pair(null, nPos)); + if (it == mData.end()) return null; + return it->first; +} + ScViewDataTable::ScViewDataTable() : eZoomType( SvxZoomType::PERCENT ), aZoomX( 1,1 ), _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits