desktop/source/lib/init.cxx | 18 +++ include/vcl/ITiledRenderable.hxx | 13 ++ sc/inc/docuno.hxx | 3 sc/source/ui/docshell/olinefun.cxx | 30 ++++- sc/source/ui/inc/dbfunc.hxx | 3 sc/source/ui/inc/tabvwsh.hxx | 10 + sc/source/ui/undo/undoblk.cxx | 9 - sc/source/ui/undo/undoblk2.cxx | 6 - sc/source/ui/undo/undodat.cxx | 10 + sc/source/ui/unoobj/docuno.cxx | 13 ++ sc/source/ui/view/cellsh1.cxx | 5 sc/source/ui/view/dbfunc3.cxx | 53 +++++++++ sc/source/ui/view/gridwin.cxx | 12 +- sc/source/ui/view/tabview.cxx | 208 ++++++++++++++++++++++++++++++++++++- sc/source/ui/view/tabvwshc.cxx | 38 +++++- sc/source/ui/view/viewfunc.cxx | 14 -- 16 files changed, 408 insertions(+), 37 deletions(-)
New commits: commit 6964953c5a86ef02fa9320e1db4d6bd81cee5001 Author: Marco Cecchetti <marco.cecche...@collabora.com> Date: Mon Nov 27 17:50:26 2017 +0100 lok - calc: outline and group handling Change-Id: Ibb287468653bc381acf034dcb8531c5faf61aef3 Reviewed-on: https://gerrit.libreoffice.org/45416 Reviewed-by: Jan Holesovsky <ke...@collabora.com> Tested-by: Jan Holesovsky <ke...@collabora.com> diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 307418fcd55c..fe046459751f 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -3009,6 +3009,10 @@ static char* doc_getCommandValues(LibreOfficeKitDocument* pThis, const char* pCo int nY = 0; int nWidth = 0; int nHeight = 0; + bool bColumn = false; + int nLevel = -1; + int nGroupIndex = -2; + bool bHidden = false; OString aArguments = aCommand.copy(aViewRowColumnHeaders.getLength() + 1); sal_Int32 nParamIndex = 0; do @@ -3034,9 +3038,23 @@ static char* doc_getCommandValues(LibreOfficeKitDocument* pThis, const char* pCo nWidth = aValue.toInt32(); else if (aKey == "height") nHeight = aValue.toInt32(); + else if (aKey == "columnOutline") + bColumn = aValue.toBoolean(); + else if (aKey == "groupLevel") + nLevel = aValue.toInt32(); + else if (aKey == "groupIndex") + nGroupIndex = aValue.toInt32(); + else if (aKey == "groupHidden") + bHidden = aValue.toBoolean(); } while (nParamIndex >= 0); + aRectangle = Rectangle(nX, nY, nX + nWidth, nY + nHeight); + + if (nGroupIndex != -2) + { + pDoc->setOutlineState(bColumn, nLevel, nGroupIndex, bHidden); + } } OUString aHeaders = pDoc->getRowColumnHeaders(aRectangle); diff --git a/include/vcl/ITiledRenderable.hxx b/include/vcl/ITiledRenderable.hxx index ae3ba9e76c3c..95676d751244 100644 --- a/include/vcl/ITiledRenderable.hxx +++ b/include/vcl/ITiledRenderable.hxx @@ -151,6 +151,19 @@ public: } /** + * Show/Hide a single row/column header outline for Calc dosuments. + * + * @param bColumn - if we are dealing with a column or row group + * @param nLevel - the level to which the group belongs + * @param nIndex - the group entry index + * @param bHidden - the new group state (collapsed/expanded) + */ + virtual void setOutlineState(bool /*bColumn*/, int /*nLevel*/, int /*nIndex*/, bool /*bHidden*/) + { + return; + } + + /** * Get position and content of row/column headers of Calc documents. * * @param rRectangle - if not empty, then limit the output only to the area of this rectangle diff --git a/sc/inc/docuno.hxx b/sc/inc/docuno.hxx index 917b211a82a1..e37f11a9ba49 100644 --- a/sc/inc/docuno.hxx +++ b/sc/inc/docuno.hxx @@ -409,6 +409,9 @@ public: /// @see vcl::ITiledRenderable::setClientZoom(). virtual void setClientZoom(int nTilePixelWidth, int nTilePixelHeight, int nTileTwipWidth, int nTileTwipHeight) override; + /// @see vcl::ITiledRenderable::setOutlineState(). + virtual void setOutlineState(bool bColumn, int nLevel, int nIndex, bool bHidden) override; + /// @see vcl::ITiledRenderable::getRowColumnHeaders(). virtual OUString getRowColumnHeaders(const Rectangle& rRectangle) override; diff --git a/sc/source/ui/docshell/olinefun.cxx b/sc/source/ui/docshell/olinefun.cxx index a96eadf2d964..c2e56231cc74 100644 --- a/sc/source/ui/docshell/olinefun.cxx +++ b/sc/source/ui/docshell/olinefun.cxx @@ -27,6 +27,10 @@ #include "globstr.hrc" #include "sc.hrc" +#include <tabvwsh.hxx> +#include <sfx2/lokhelper.hxx> +#include <comphelper/lok.hxx> + static void lcl_InvalidateOutliner( SfxBindings* pBindings ) { if ( pBindings ) @@ -402,6 +406,10 @@ bool ScOutlineDocFunc::SelectLevel( SCTAB nTab, bool bColumns, sal_uInt16 nLevel rDocShell.SetDocumentModified(); lcl_InvalidateOutliner( rDocShell.GetViewBindings() ); + ScTabViewShell* pViewSh = rDocShell.GetBestViewShell(); + if ( pViewSh ) + pViewSh->OnLOKShowHideOutline(bColumns, 0); + return true; } @@ -462,6 +470,7 @@ bool ScOutlineDocFunc::ShowMarkedOutlines( const ScRange& rRange, bool bRecord ) if (nEnd>nMax) nMax=nEnd; } } + const SCCOLROW nMinStartCol = nMin; for ( i=nMin; i<=nMax; i++ ) rDoc.ShowCol( static_cast<SCCOL>(i), nTab, true ); @@ -483,6 +492,7 @@ bool ScOutlineDocFunc::ShowMarkedOutlines( const ScRange& rRange, bool bRecord ) if (nEnd>nMax) nMax=nEnd; } } + const SCCOLROW nMinStartRow = nMin; for ( i=nMin; i<=nMax; i++ ) { // show several rows together, don't show filtered rows @@ -494,6 +504,7 @@ bool ScOutlineDocFunc::ShowMarkedOutlines( const ScRange& rRange, bool bRecord ) i = nFilterEnd; } + rDoc.SetDrawPageSize(nTab); rDoc.UpdatePageBreaks( nTab ); @@ -502,6 +513,13 @@ bool ScOutlineDocFunc::ShowMarkedOutlines( const ScRange& rRange, bool bRecord ) bDone = true; lcl_InvalidateOutliner( rDocShell.GetViewBindings() ); + + ScTabViewShell* pViewSh = rDocShell.GetBestViewShell(); + if ( pViewSh ) + { + pViewSh->OnLOKShowHideOutline(/*columns: */ true, nMinStartCol - 1); + pViewSh->OnLOKShowHideOutline(/*columns: */ false, nMinStartRow - 1); + } } return bDone; @@ -681,7 +699,11 @@ bool ScOutlineDocFunc::ShowOutline( SCTAB nTab, bool bColumns, sal_uInt16 nLevel lcl_InvalidateOutliner( rDocShell.GetViewBindings() ); - return true; //! immer ??? + ScTabViewShell* pViewSh = rDocShell.GetBestViewShell(); + if ( pViewSh ) + pViewSh->OnLOKShowHideOutline(bColumns, nStart - 1); + + return true; //! always ??? } bool ScOutlineDocFunc::HideOutline( SCTAB nTab, bool bColumns, sal_uInt16 nLevel, sal_uInt16 nEntry, @@ -740,7 +762,11 @@ bool ScOutlineDocFunc::HideOutline( SCTAB nTab, bool bColumns, sal_uInt16 nLevel lcl_InvalidateOutliner( rDocShell.GetViewBindings() ); - return true; //! immer ??? + ScTabViewShell* pViewSh = rDocShell.GetBestViewShell(); + if ( pViewSh ) + pViewSh->OnLOKShowHideOutline(bColumns, nStart - 1); + + return true; //! always ??? } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/dbfunc.hxx b/sc/source/ui/inc/dbfunc.hxx index ad71348a1e56..6ec96c6103ec 100644 --- a/sc/source/ui/inc/dbfunc.hxx +++ b/sc/source/ui/inc/dbfunc.hxx @@ -103,6 +103,7 @@ public: void SelectLevel( bool bColumns, sal_uInt16 nLevel, bool bRecord = true ); + void SetOutlineState( bool bColumn, sal_uInt16 nLevel, sal_uInt16 nEntry, bool bHidden); void ShowOutline( bool bColumns, sal_uInt16 nLevel, sal_uInt16 nEntry, bool bRecord = true, bool bPaint = true ); void HideOutline( bool bColumns, sal_uInt16 nLevel, sal_uInt16 nEntry, @@ -115,6 +116,8 @@ public: void UpdateCharts(bool bAllCharts); // Default: am Cursor static sal_uInt16 DoUpdateCharts( const ScAddress& rPos, ScDocument* pDoc, bool bAllCharts ); + + void OnLOKShowHideOutline(bool bColumns, SCROW nStartRow); }; #endif diff --git a/sc/source/ui/inc/tabvwsh.hxx b/sc/source/ui/inc/tabvwsh.hxx index 9c304ee164b9..2df115f27226 100644 --- a/sc/source/ui/inc/tabvwsh.hxx +++ b/sc/source/ui/inc/tabvwsh.hxx @@ -91,6 +91,13 @@ enum ObjectSelectionType OST_Media }; +enum HeaderType +{ + COLUMN_HEADER, + ROW_HEADER, + BOTH_HEADERS +}; + class SC_DLLPUBLIC ScTabViewShell: public SfxViewShell, public ScDBFunc { private: @@ -398,7 +405,8 @@ public: void NotifyCursor(SfxViewShell* pViewShell) const override; css::uno::Reference<css::drawing::XShapes> getSelectedXShapes(); /// Emits a LOK_CALLBACK_INVALIDATE_HEADER for all views whose current tab is equal to nCurrentTabIndex - static void notifyAllViewsHeaderInvalidation(const OString& rPayload, SCTAB nCurrentTabIndex = -1); + static void notifyAllViewsHeaderInvalidation(HeaderType eHeaderType, SCTAB nCurrentTabIndex = -1); + static void notifyAllViewsHeaderInvalidation(bool Columns, SCTAB nCurrentTabIndex = -1); }; #endif diff --git a/sc/source/ui/undo/undoblk.cxx b/sc/source/ui/undo/undoblk.cxx index 6af80db9eb15..97781f21f799 100644 --- a/sc/source/ui/undo/undoblk.cxx +++ b/sc/source/ui/undo/undoblk.cxx @@ -279,12 +279,11 @@ void ScUndoInsertCells::DoChange( const bool bUndo ) if (comphelper::LibreOfficeKit::isActive()) { if (eCmd == INS_INSCOLS_BEFORE || eCmd == INS_INSCOLS_AFTER || eCmd == INS_CELLSRIGHT) - ScTabViewShell::notifyAllViewsHeaderInvalidation("column", pViewShell->GetViewData().GetTabNo()); + ScTabViewShell::notifyAllViewsHeaderInvalidation(COLUMN_HEADER, pViewShell->GetViewData().GetTabNo()); if (eCmd == INS_INSROWS_BEFORE || eCmd == INS_INSROWS_AFTER || eCmd == INS_CELLSDOWN) - ScTabViewShell::notifyAllViewsHeaderInvalidation("row", pViewShell->GetViewData().GetTabNo()); + ScTabViewShell::notifyAllViewsHeaderInvalidation(ROW_HEADER, pViewShell->GetViewData().GetTabNo()); } - } } @@ -541,10 +540,10 @@ void ScUndoDeleteCells::DoChange( const bool bUndo ) if (comphelper::LibreOfficeKit::isActive()) { if (eCmd == DEL_DELCOLS || eCmd == DEL_CELLSLEFT) - ScTabViewShell::notifyAllViewsHeaderInvalidation("column", pViewShell->GetViewData().GetTabNo()); + ScTabViewShell::notifyAllViewsHeaderInvalidation(COLUMN_HEADER, pViewShell->GetViewData().GetTabNo()); if (eCmd == DEL_DELROWS || eCmd == DEL_CELLSUP) - ScTabViewShell::notifyAllViewsHeaderInvalidation("row", pViewShell->GetViewData().GetTabNo()); + ScTabViewShell::notifyAllViewsHeaderInvalidation(ROW_HEADER, pViewShell->GetViewData().GetTabNo()); } } diff --git a/sc/source/ui/undo/undoblk2.cxx b/sc/source/ui/undo/undoblk2.cxx index 8a1247cbca14..50589d7a8ace 100644 --- a/sc/source/ui/undo/undoblk2.cxx +++ b/sc/source/ui/undo/undoblk2.cxx @@ -131,11 +131,7 @@ void ScUndoWidthOrHeight::Undo() if ( nCurrentTab < nStartTab || nCurrentTab > nEndTab ) pViewShell->SetTabNo( nStartTab ); - if (comphelper::LibreOfficeKit::isActive()) - { - OString aPayload = bWidth ? "column" : "row"; - ScTabViewShell::notifyAllViewsHeaderInvalidation(aPayload, pViewShell->GetViewData().GetTabNo()); - } + ScTabViewShell::notifyAllViewsHeaderInvalidation(bWidth, pViewShell->GetViewData().GetTabNo()); } EndUndo(); diff --git a/sc/source/ui/undo/undodat.cxx b/sc/source/ui/undo/undodat.cxx index 1595bf118e74..c17333a2370e 100644 --- a/sc/source/ui/undo/undodat.cxx +++ b/sc/source/ui/undo/undodat.cxx @@ -44,6 +44,8 @@ #include "refundo.hxx" #include "markdata.hxx" +#include <sfx2/lokhelper.hxx> +#include <comphelper/lok.hxx> // Show or hide outline groups @@ -182,6 +184,8 @@ void ScUndoMakeOutline::Undo() pDocShell->PostPaint(0,0,nTab,MAXCOL,MAXROW,nTab,PaintPartFlags::Grid|PaintPartFlags::Left|PaintPartFlags::Top|PaintPartFlags::Size); + ScTabViewShell::notifyAllViewsHeaderInvalidation( bColumns, nTab ); + EndUndo(); } @@ -374,6 +378,10 @@ void ScUndoOutlineBlock::Undo() pDocShell->PostPaint(0,0,nTab,MAXCOL,MAXROW,nTab,PaintPartFlags::Grid|PaintPartFlags::Left|PaintPartFlags::Top); + + pViewShell->OnLOKShowHideOutline(/*columns: */ true, nStartCol - 1); + pViewShell->OnLOKShowHideOutline(/*columns: */ false, nStartRow - 1); + EndUndo(); } @@ -463,6 +471,8 @@ void ScUndoRemoveAllOutlines::Undo() pDocShell->PostPaint(0,0,nTab,MAXCOL,MAXROW,nTab,PaintPartFlags::Grid|PaintPartFlags::Left|PaintPartFlags::Top|PaintPartFlags::Size); + ScTabViewShell::notifyAllViewsHeaderInvalidation(BOTH_HEADERS, nTab); + EndUndo(); } diff --git a/sc/source/ui/unoobj/docuno.cxx b/sc/source/ui/unoobj/docuno.cxx index 473a8dcb17ac..0d5e4f50a159 100644 --- a/sc/source/ui/unoobj/docuno.cxx +++ b/sc/source/ui/unoobj/docuno.cxx @@ -958,6 +958,19 @@ void ScModelObj::setClientZoom(int nTilePixelWidth_, int nTilePixelHeight_, int mnTileTwipHeight = nTileTwipHeight_; } +void ScModelObj::setOutlineState(bool bColumn, int nLevel, int nIndex, bool bHidden) +{ + ScViewData* pViewData = ScDocShell::GetViewData(); + + if (!pViewData) + return; + + ScDBFunc* pFunc = pViewData->GetView(); + + if (pFunc) + pFunc->SetOutlineState(bColumn, nLevel, nIndex, bHidden); +} + OUString ScModelObj::getRowColumnHeaders(const Rectangle& rRectangle) { ScViewData* pViewData = ScDocShell::GetViewData(); diff --git a/sc/source/ui/view/cellsh1.cxx b/sc/source/ui/view/cellsh1.cxx index 6c0a2ec22f79..bbce79c3564a 100644 --- a/sc/source/ui/view/cellsh1.cxx +++ b/sc/source/ui/view/cellsh1.cxx @@ -1169,7 +1169,7 @@ void ScCellShell::ExecuteEdit( SfxRequest& rReq ) bColumns = true; else if ( !GetViewData()->SimpleColMarked() && GetViewData()->SimpleRowMarked() ) bColumns = false; - else + else if ( !comphelper::LibreOfficeKit::isActive() ) // TODO: handle this case in LOK too { ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); OSL_ENSURE(pFact, "ScAbstractFactory create fail!"); @@ -1228,7 +1228,8 @@ void ScCellShell::ExecuteEdit( SfxRequest& rReq ) { bool bColPoss, bRowPoss; pTabViewShell->TestRemoveOutline( bColPoss, bRowPoss ); - if ( bColPoss && bRowPoss ) + // TODO: handle this case in LOK too + if ( bColPoss && bRowPoss && !comphelper::LibreOfficeKit::isActive() ) { ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); OSL_ENSURE(pFact, "ScAbstractFactory create fail!"); diff --git a/sc/source/ui/view/dbfunc3.cxx b/sc/source/ui/view/dbfunc3.cxx index 304a1428d6bb..95e104536d59 100644 --- a/sc/source/ui/view/dbfunc3.cxx +++ b/sc/source/ui/view/dbfunc3.cxx @@ -68,6 +68,9 @@ #include "stringutil.hxx" #include "tabvwsh.hxx" +#include <sfx2/lokhelper.hxx> +#include <comphelper/lok.hxx> + #include <list> #include <memory> #include <unordered_set> @@ -99,6 +102,8 @@ void ScDBFunc::MakeOutline( bool bColumns, bool bRecord ) ScDocShell* pDocSh = GetViewData().GetDocShell(); ScOutlineDocFunc aFunc(*pDocSh); aFunc.MakeOutline( aRange, bColumns, bRecord, false ); + + ScTabViewShell::notifyAllViewsHeaderInvalidation(bColumns, GetViewData().GetTabNo()); } else ErrorMessage(STR_NOMULTISELECT); @@ -114,6 +119,8 @@ void ScDBFunc::RemoveOutline( bool bColumns, bool bRecord ) ScDocShell* pDocSh = GetViewData().GetDocShell(); ScOutlineDocFunc aFunc(*pDocSh); aFunc.RemoveOutline( aRange, bColumns, bRecord, false ); + + ScTabViewShell::notifyAllViewsHeaderInvalidation(bColumns, GetViewData().GetTabNo()); } else ErrorMessage(STR_NOMULTISELECT); @@ -187,7 +194,10 @@ void ScDBFunc::RemoveAllOutlines( bool bRecord ) bool bOk = aFunc.RemoveAllOutlines( nTab, bRecord ); if (bOk) + { UpdateScrollBars(); + ScTabViewShell::notifyAllViewsHeaderInvalidation(BOTH_HEADERS, GetViewData().GetTabNo()); + } } // auto outlines @@ -224,6 +234,20 @@ void ScDBFunc::SelectLevel( bool bColumns, sal_uInt16 nLevel, bool bRecord ) // show individual outline groups +void ScDBFunc::SetOutlineState( bool bColumns, sal_uInt16 nLevel, sal_uInt16 nEntry, bool bHidden) +{ + const sal_uInt16 nHeadEntry = static_cast< sal_uInt16 >( -1 ); + if ( nEntry == nHeadEntry) + SelectLevel( bColumns, sal::static_int_cast<sal_uInt16>(nLevel) ); + else + { + if ( !bHidden ) + ShowOutline( bColumns, sal::static_int_cast<sal_uInt16>(nLevel), sal::static_int_cast<sal_uInt16>(nEntry) ); + else + HideOutline( bColumns, sal::static_int_cast<sal_uInt16>(nLevel), sal::static_int_cast<sal_uInt16>(nEntry) ); + } +} + void ScDBFunc::ShowOutline( bool bColumns, sal_uInt16 nLevel, sal_uInt16 nEntry, bool bRecord, bool bPaint ) { SCTAB nTab = GetViewData().GetTabNo(); @@ -2239,4 +2263,33 @@ void ScDBFunc::RepeatDB( bool bRecord ) ErrorMessage(STR_MSSG_REPEATDB_0); } +void ScDBFunc::OnLOKShowHideOutline(bool bColumns, SCCOLROW nStart) +{ + if (!comphelper::LibreOfficeKit::isActive()) + return; + + SCTAB nCurrentTabIndex = GetViewData().GetTabNo(); + SfxViewShell* pViewShell = SfxViewShell::GetFirst(); + while (pViewShell) + { + ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(pViewShell); + if (pTabViewShell) + { + if (bColumns) + pTabViewShell->GetViewData().GetLOKWidthHelper(nCurrentTabIndex)->invalidateByIndex(nStart); + else + pTabViewShell->GetViewData().GetLOKHeightHelper(nCurrentTabIndex)->invalidateByIndex(nStart); + + if (pTabViewShell->getPart() == nCurrentTabIndex) + { + pTabViewShell->ShowCursor(); + pTabViewShell->MarkDataChanged(); + } + } + pViewShell = SfxViewShell::GetNext(*pViewShell); + } + + ScTabViewShell::notifyAllViewsHeaderInvalidation(bColumns, nCurrentTabIndex); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx index 4a716cf536fb..bfea6b18804c 100644 --- a/sc/source/ui/view/gridwin.cxx +++ b/sc/source/ui/view/gridwin.cxx @@ -5750,8 +5750,18 @@ OString ScGridWindow::getCellCursor(const Fraction& rZoomX, const Fraction& rZoo double fPPTX = pViewData->GetPPTX(); double fPPTY = pViewData->GetPPTY(); + // make it a slim cell cursor, but not empty + if (nSizeXPix == 0) + nSizeXPix = 1; + + if (nSizeYPix == 0) + nSizeYPix = 1; + + long nSizeXTw = rtl::math::round(nSizeXPix / fPPTX); + long nSizeYTw = rtl::math::round(nSizeYPix / fPPTY); + Rectangle aRect(Point(rtl::math::round(aScrPos.getX() / fPPTX), rtl::math::round(aScrPos.getY() / fPPTY)), - Size(rtl::math::round(nSizeXPix / fPPTX), rtl::math::round(nSizeYPix / fPPTY))); + Size(nSizeXTw, nSizeYTw)); pViewData->SetZoom(defaultZoomX, defaultZoomY, true); diff --git a/sc/source/ui/view/tabview.cxx b/sc/source/ui/view/tabview.cxx index 4aef7be67b16..de425afdd698 100644 --- a/sc/source/ui/view/tabview.cxx +++ b/sc/source/ui/view/tabview.cxx @@ -2560,6 +2560,148 @@ void BoundsProvider<IndexType>::GetIndexTowards( } } +namespace +{ + +void lcl_getGroupIndexes(const ScOutlineArray& rArray, SCCOLROW nStart, SCCOLROW nEnd, std::vector<size_t>& rGroupIndexes) +{ + rGroupIndexes.clear(); + const size_t nGroupDepth = rArray.GetDepth(); + rGroupIndexes.resize(nGroupDepth); + + // Get first group per each level + for (size_t nLevel = 0; nLevel < nGroupDepth; ++nLevel) + { + if (rArray.GetCount(nLevel)) + { + // look for a group inside the [nStartRow+1, nEndRow-1] range + size_t nIndex; + bool bFound = rArray.GetEntryIndexInRange(nLevel, nStart + 1, nEnd - 1, nIndex); + if (bFound) + { + if (nIndex > 0) + { + // is there a prevoius group not inside the range + // but anyway intersecting it ? + const ScOutlineEntry* pPrevEntry = rArray.GetEntry(nLevel, nIndex - 1); + if (pPrevEntry && nStart < pPrevEntry->GetEnd()) + { + --nIndex; + } + } + } + else + { + // look for a group which contains nStartRow+1 + bFound = rArray.GetEntryIndex(nLevel, nStart + 1, nIndex); + if (!bFound) + { + // look for a group which contains nEndRow-1 + bFound = rArray.GetEntryIndex(nLevel, nEnd - 1, nIndex); + } + } + + if (bFound) + { + // skip groups with no visible control + bFound = false; + while (nIndex < rArray.GetCount(nLevel)) + { + const ScOutlineEntry* pEntry = rArray.GetEntry(nLevel, nIndex); + if (pEntry && pEntry->IsVisible()) + { + bFound = true; + break; + } + if (pEntry && pEntry->GetStart() > nEnd - 1) + { + break; + } + ++nIndex; + } + } + + rGroupIndexes[nLevel] = bFound ? nIndex : -1; + } + } +} + +void lcl_createGroupsData( + SCCOLROW nHeaderIndex, SCCOLROW nEnd, long nSizePx, long nTotalTwips, + const ScOutlineArray& rArray, std::vector<size_t>& rGroupIndexes, + std::vector<long>& rGroupStartPositions, OUString& rGroupsBuffer) +{ + const size_t nGroupDepth = rArray.GetDepth(); + // create string data for group controls + for (size_t nLevel = nGroupDepth - 1; nLevel != size_t(-1); --nLevel) + { + size_t nIndex = rGroupIndexes[nLevel]; + if (nIndex == size_t(-1)) + continue; + const ScOutlineEntry* pEntry = rArray.GetEntry(nLevel, nIndex); + if (pEntry) + { + if (nHeaderIndex < pEntry->GetStart()) + { + continue; + } + else if (nHeaderIndex == pEntry->GetStart()) + { + rGroupStartPositions[nLevel] = nTotalTwips - nSizePx * TWIPS_PER_PIXEL; + } + else if (nHeaderIndex > pEntry->GetStart() && (nHeaderIndex < nEnd - 1 && nHeaderIndex < pEntry->GetEnd())) + { + // for handling group started before the current view range + if (rGroupStartPositions[nLevel] < 0) + rGroupStartPositions[nLevel] *= -TWIPS_PER_PIXEL; + break; + } + if (nHeaderIndex == pEntry->GetEnd() || (nHeaderIndex == nEnd - 1 && rGroupStartPositions[nLevel] != -1)) + { + // nRow is the end row of a group or is the last row and a group started and not yet ended + // append a new group control data + if (rGroupsBuffer.endsWith("}")) + { + rGroupsBuffer += ", "; + } + + bool bGroupHidden = pEntry->IsHidden(); + + OUString aGroupData; + aGroupData += "{ \"level\": \"" + OUString::number(nLevel + 1) + "\", "; + aGroupData += "\"index\": \"" + OUString::number(nIndex) + "\", "; + aGroupData += "\"startPos\": \"" + OUString::number(rGroupStartPositions[nLevel]) + "\", "; + aGroupData += "\"endPos\": \"" + OUString::number(nTotalTwips) + "\", "; + aGroupData += "\"hidden\": \"" + OUString::number(bGroupHidden) + "\" }"; + + rGroupsBuffer += aGroupData; + + // look for the next visible group control at level nLevel + bool bFound = false; + ++nIndex; + while (nIndex < rArray.GetCount(nLevel)) + { + pEntry = rArray.GetEntry(nLevel, nIndex); + if (pEntry && pEntry->IsVisible()) + { + bFound = true; + break; + } + if (pEntry && pEntry->GetStart() > nEnd) + { + break; + } + ++nIndex; + } + rGroupIndexes[nLevel] = bFound ? nIndex : -1; + rGroupStartPositions[nLevel] = -1; + } + } + } +} + +} // anonymous namespace + OUString ScTabView::getRowColumnHeaders(const Rectangle& rRectangle) { ScDocument* pDoc = aViewData.GetDocument(); @@ -2618,6 +2760,20 @@ OUString ScTabView::getRowColumnHeaders(const Rectangle& rRectangle) SAL_INFO("sc.lok.header", "Row Header: visible rows: " << nVisibleRows); + // Get row groups + // per each level store the index of the first group intersecting + // [nStartRow, nEndRow] range + + const ScOutlineTable* pTable = pDoc->GetOutlineTable(nTab); + const ScOutlineArray* pRowArray = pTable ? &(pTable->GetRowArray()) : nullptr; + size_t nRowGroupDepth = 0; + std::vector<size_t> aRowGroupIndexes; + if (pTable) + { + nRowGroupDepth = pRowArray->GetDepth(); + lcl_getGroupIndexes(*pRowArray, nStartRow, nEndRow, aRowGroupIndexes); + } + /// 2) if we are approaching current max tiled row, signal a size changed event /// and invalidate the involved area @@ -2671,15 +2827,27 @@ OUString ScTabView::getRowColumnHeaders(const Rectangle& rRectangle) { OUString aText = OUString::number(nStartRow + 1); aBuffer.append("{ \"text\": \"").append(aText).append("\", "); - aBuffer.append("\"size\": \"").append(OUString::number(nTotalPixels * TWIPS_PER_PIXEL)).append("\" }"); + aBuffer.append("\"size\": \"").append(OUString::number(nTotalPixels * TWIPS_PER_PIXEL)).append("\", "); + aBuffer.append("\"groupLevels\": \"").append(OUString::number(nRowGroupDepth)).append("\" }"); } + OUString aRowGroupsBuffer; + aRowGroupsBuffer += "\"rowGroups\": [\n"; + std::vector<long> aRowGroupStartPositions(nRowGroupDepth, -nTotalPixels); long nPrevSizePx = -1; for (SCROW nRow = nStartRow + 1; nRow < nEndRow; ++nRow) { // nSize will be 0 for hidden rows. const long nSizePx = lcl_GetRowHeightPx(pDoc, nRow, nTab); nTotalPixels += nSizePx; + const long nTotalTwips = nTotalPixels * TWIPS_PER_PIXEL; + + if (nRowGroupDepth > 0) + { + lcl_createGroupsData(nRow, nEndRow, nSizePx, nTotalTwips, + *pRowArray, aRowGroupIndexes, aRowGroupStartPositions, aRowGroupsBuffer); + } + if (nRow < nEndRow - 1 && nSizePx == nPrevSizePx) continue; nPrevSizePx = nSizePx; @@ -2687,10 +2855,13 @@ OUString ScTabView::getRowColumnHeaders(const Rectangle& rRectangle) OUString aText = pRowBar[SC_SPLIT_BOTTOM]->GetEntryText(nRow); aBuffer.append(", "); aBuffer.append("{ \"text\": \"").append(aText).append("\", "); - aBuffer.append("\"size\": \"").append(OUString::number(nTotalPixels * TWIPS_PER_PIXEL)).append("\" }"); + aBuffer.append("\"size\": \"").append(OUString::number(nTotalTwips)).append("\" }"); } + aRowGroupsBuffer += "]"; aBuffer.append("]"); + if (nRowGroupDepth > 0) + aBuffer.append(",\n").append(aRowGroupsBuffer); /// end collecting ROWS @@ -2731,6 +2902,19 @@ OUString ScTabView::getRowColumnHeaders(const Rectangle& rRectangle) nVisibleCols = 10; + // Get column groups + // per each level store the index of the first group intersecting + // [nStartCol, nEndCol] range + + const ScOutlineArray* pColArray = pTable ? &(pTable->GetColArray()) : nullptr; + size_t nColGroupDepth = 0; + std::vector<size_t> aColGroupIndexes; + if (pTable) + { + nColGroupDepth = pColArray->GetDepth(); + lcl_getGroupIndexes(*pColArray, nStartCol, nEndCol, aColGroupIndexes); + } + /// 2) if we are approaching current max tiled column, signal a size changed event /// and invalidate the involved area @@ -2782,27 +2966,41 @@ OUString ScTabView::getRowColumnHeaders(const Rectangle& rRectangle) { OUString aText = OUString::number(nStartCol + 1); aBuffer.append("{ \"text\": \"").append(aText).append("\", "); - aBuffer.append("\"size\": \"").append(OUString::number(nTotalPixels * TWIPS_PER_PIXEL)).append("\" }"); + aBuffer.append("\"size\": \"").append(OUString::number(nTotalPixels * TWIPS_PER_PIXEL)).append("\", "); + aBuffer.append("\"groupLevels\": \"").append(OUString::number(nColGroupDepth)).append("\" }"); } + OUString aColGroupsBuffer; + aColGroupsBuffer += "\"columnGroups\": [\n"; + std::vector<long> aColGroupStartPositions(nColGroupDepth, -nTotalPixels); nPrevSizePx = -1; for (SCCOL nCol = nStartCol + 1; nCol < nEndCol; ++nCol) { // nSize will be 0 for hidden columns. const long nSizePx = lcl_GetColWidthPx(pDoc, nCol, nTab); nTotalPixels += nSizePx; + const long nTotalTwips = nTotalPixels * TWIPS_PER_PIXEL; + + if (nColGroupDepth > 0) + { + lcl_createGroupsData(nCol, nEndCol, nSizePx, nTotalTwips, + *pColArray, aColGroupIndexes, aColGroupStartPositions, aColGroupsBuffer); + } + if (nCol < nEndCol - 1 && nSizePx == nPrevSizePx) continue; nPrevSizePx = nSizePx; - OUString aText = OUString::number(nCol + 1); aBuffer.append(", "); aBuffer.append("{ \"text\": \"").append(aText).append("\", "); - aBuffer.append("\"size\": \"").append(OUString::number(nTotalPixels * TWIPS_PER_PIXEL)).append("\" }"); + aBuffer.append("\"size\": \"").append(OUString::number(nTotalTwips)).append("\" }"); } + aColGroupsBuffer += "]"; aBuffer.append("]"); + if (nColGroupDepth > 0) + aBuffer.append(",\n").append(aColGroupsBuffer); /// end collecting COLs aBuffer.append("\n}"); diff --git a/sc/source/ui/view/tabvwshc.cxx b/sc/source/ui/view/tabvwshc.cxx index 287947424165..fa92b345ff32 100644 --- a/sc/source/ui/view/tabvwshc.cxx +++ b/sc/source/ui/view/tabvwshc.cxx @@ -551,20 +551,44 @@ void ScTabViewShell::NotifyCursor(SfxViewShell* pOtherShell) const pWin->updateLibreOfficeKitCellCursor(pOtherShell); } -void ScTabViewShell::notifyAllViewsHeaderInvalidation(const OString& rPayload, SCTAB nCurrentTabIndex) +void ScTabViewShell::notifyAllViewsHeaderInvalidation(HeaderType eHeaderType, SCTAB nCurrentTabIndex) { - SfxViewShell* pViewShell = SfxViewShell::GetFirst(); - while (pViewShell) + if (comphelper::LibreOfficeKit::isActive()) { - ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(pViewShell); - if (pTabViewShell && (nCurrentTabIndex == -1 || pTabViewShell->getPart() == nCurrentTabIndex)) + OString aPayload; + switch (eHeaderType) { - pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_INVALIDATE_HEADER, rPayload.getStr()); + case COLUMN_HEADER: + aPayload = "column"; + break; + case ROW_HEADER: + aPayload = "row"; + break; + case BOTH_HEADERS: + default: + aPayload = "all"; + break; + } + + SfxViewShell* pViewShell = SfxViewShell::GetFirst(); + while (pViewShell) + { + ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(pViewShell); + if (pTabViewShell && (nCurrentTabIndex == -1 || pTabViewShell->getPart() == nCurrentTabIndex)) + { + pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_INVALIDATE_HEADER, aPayload.getStr()); + } + pViewShell = SfxViewShell::GetNext(*pViewShell); } - pViewShell = SfxViewShell::GetNext(*pViewShell); } } +void ScTabViewShell::notifyAllViewsHeaderInvalidation(bool bColumns, SCTAB nCurrentTabIndex) +{ + HeaderType eHeaderType = bColumns ? COLUMN_HEADER : ROW_HEADER; + ScTabViewShell::notifyAllViewsHeaderInvalidation(eHeaderType, nCurrentTabIndex); +} + bool ScTabViewShell::UseSubTotal(ScRangeList* pRangeList) { bool bSubTotal = false; diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx index b8208b828106..f77419050127 100644 --- a/sc/source/ui/view/viewfunc.cxx +++ b/sc/source/ui/view/viewfunc.cxx @@ -1621,10 +1621,10 @@ bool ScViewFunc::InsertCells( InsCellCmd eCmd, bool bRecord, bool bPartOfPaste ) if (comphelper::LibreOfficeKit::isActive()) { if (bInsertCols) - ScTabViewShell::notifyAllViewsHeaderInvalidation("column", GetViewData().GetTabNo()); + ScTabViewShell::notifyAllViewsHeaderInvalidation(COLUMN_HEADER, GetViewData().GetTabNo()); if (bInsertRows) - ScTabViewShell::notifyAllViewsHeaderInvalidation("row", GetViewData().GetTabNo()); + ScTabViewShell::notifyAllViewsHeaderInvalidation(ROW_HEADER, GetViewData().GetTabNo()); } } return bSuccess; @@ -1696,10 +1696,10 @@ void ScViewFunc::DeleteCells( DelCellCmd eCmd ) if (comphelper::LibreOfficeKit::isActive()) { if (eCmd == DEL_DELCOLS) - ScTabViewShell::notifyAllViewsHeaderInvalidation("column", GetViewData().GetTabNo()); + ScTabViewShell::notifyAllViewsHeaderInvalidation(COLUMN_HEADER, GetViewData().GetTabNo()); if (eCmd == DEL_DELROWS) - ScTabViewShell::notifyAllViewsHeaderInvalidation("row", GetViewData().GetTabNo()); + ScTabViewShell::notifyAllViewsHeaderInvalidation(ROW_HEADER, GetViewData().GetTabNo()); } } else @@ -2297,11 +2297,7 @@ void ScViewFunc::SetWidthOrHeight( } } - if (comphelper::LibreOfficeKit::isActive()) - { - OString aPayload = bWidth ? "column" : "row"; - ScTabViewShell::notifyAllViewsHeaderInvalidation(aPayload, GetViewData().GetTabNo()); - } + ScTabViewShell::notifyAllViewsHeaderInvalidation(bWidth, GetViewData().GetTabNo()); } // column width/row height (via marked range) _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits