[Libreoffice-commits] core.git: desktop/source include/vcl sc/inc sc/source

Marco Cecchetti marco.cecchetti at collabora.com
Wed Nov 29 11:45:13 UTC 2017


 desktop/source/lib/init.cxx        |   18 +++
 include/vcl/ITiledRenderable.hxx   |   13 ++
 sc/inc/docuno.hxx                  |    3 
 sc/source/ui/docshell/olinefun.cxx |   27 ++++
 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     |   14 ++
 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(+), 35 deletions(-)

New commits:
commit a2b70380c38dca4d075a0a866200096c6d9b4104
Author: Marco Cecchetti <marco.cecchetti at 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/45356
    Reviewed-by: Marco Cecchetti <mrcekets at gmail.com>
    Tested-by: Marco Cecchetti <mrcekets at gmail.com>

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 95d4cda6ecd9..243aba70c5b5 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -2989,6 +2989,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
@@ -3014,9 +3018,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 = tools::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 7b0720a429b7..4e5f128674ee 100644
--- a/include/vcl/ITiledRenderable.hxx
+++ b/include/vcl/ITiledRenderable.hxx
@@ -144,6 +144,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 67ee07440884..0004b03935e7 100644
--- a/sc/inc/docuno.hxx
+++ b/sc/inc/docuno.hxx
@@ -340,6 +340,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 tools::Rectangle& rRectangle) override;
 
diff --git a/sc/source/ui/docshell/olinefun.cxx b/sc/source/ui/docshell/olinefun.cxx
index fc9d50448193..6e7f42cbc635 100644
--- a/sc/source/ui/docshell/olinefun.cxx
+++ b/sc/source/ui/docshell/olinefun.cxx
@@ -23,10 +23,15 @@
 
 #include <docsh.hxx>
 #include <olinetab.hxx>
+#include <tabvwsh.hxx>
 #include <undodat.hxx>
 #include <globstr.hrc>
 #include <sc.hrc>
 
+#include <sfx2/lokhelper.hxx>
+#include <comphelper/lok.hxx>
+
+
 static void lcl_InvalidateOutliner( SfxBindings* pBindings )
 {
     if ( pBindings )
@@ -398,6 +403,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;
 }
 
@@ -458,6 +467,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 );
 
@@ -479,6 +489,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
@@ -490,6 +501,7 @@ bool ScOutlineDocFunc::ShowMarkedOutlines( const ScRange& rRange, bool bRecord )
             i = nFilterEnd;
         }
 
+
         rDoc.SetDrawPageSize(nTab);
         rDoc.UpdatePageBreaks( nTab );
 
@@ -498,6 +510,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;
@@ -677,6 +696,10 @@ bool ScOutlineDocFunc::ShowOutline( SCTAB nTab, bool bColumns, sal_uInt16 nLevel
 
     lcl_InvalidateOutliner( rDocShell.GetViewBindings() );
 
+    ScTabViewShell* pViewSh = rDocShell.GetBestViewShell();
+    if ( pViewSh )
+        pViewSh->OnLOKShowHideOutline(bColumns, nStart - 1);
+
     return true;        //! always ???
 }
 
@@ -736,6 +759,10 @@ bool ScOutlineDocFunc::HideOutline( SCTAB nTab, bool bColumns, sal_uInt16 nLevel
 
     lcl_InvalidateOutliner( rDocShell.GetViewBindings() );
 
+    ScTabViewShell* pViewSh = rDocShell.GetBestViewShell();
+    if ( pViewSh )
+        pViewSh->OnLOKShowHideOutline(bColumns, nStart - 1);
+
     return true;        //! always ???
 }
 
diff --git a/sc/source/ui/inc/dbfunc.hxx b/sc/source/ui/inc/dbfunc.hxx
index 8503868fe087..793b8c65c3c8 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 2ad0299d73cb..a6435591f18b 100644
--- a/sc/source/ui/inc/tabvwsh.hxx
+++ b/sc/source/ui/inc/tabvwsh.hxx
@@ -92,6 +92,13 @@ enum ObjectSelectionType
     OST_Media
 };
 
+enum HeaderType
+{
+    COLUMN_HEADER,
+    ROW_HEADER,
+    BOTH_HEADERS
+};
+
 class SC_DLLPUBLIC ScTabViewShell: public SfxViewShell, public ScDBFunc
 {
 private:
@@ -389,7 +396,8 @@ public:
     /// See SfxViewShell::NotifyCursor().
     void NotifyCursor(SfxViewShell* pViewShell) const override;
     /// 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);
     css::uno::Reference<css::drawing::XShapes> getSelectedXShapes();
 };
 
diff --git a/sc/source/ui/undo/undoblk.cxx b/sc/source/ui/undo/undoblk.cxx
index acaadbc0dd61..a59b5d5c4177 100644
--- a/sc/source/ui/undo/undoblk.cxx
+++ b/sc/source/ui/undo/undoblk.cxx
@@ -276,12 +276,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());
         }
-
     }
 }
 
@@ -536,10 +535,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 140cdb459b91..569905716f39 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 b7a745a87d98..b1bb0bbc88f3 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
 
@@ -180,6 +182,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();
 }
 
@@ -360,6 +364,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();
 }
 
@@ -443,6 +451,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 ca287c11b398..d5b66af921ac 100644
--- a/sc/source/ui/unoobj/docuno.cxx
+++ b/sc/source/ui/unoobj/docuno.cxx
@@ -958,6 +958,20 @@ 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 tools::Rectangle& rRectangle)
 {
     ScViewData* pViewData = ScDocShell::GetViewData();
diff --git a/sc/source/ui/view/cellsh1.cxx b/sc/source/ui/view/cellsh1.cxx
index 41d74671b5f4..2ea794a0bc99 100644
--- a/sc/source/ui/view/cellsh1.cxx
+++ b/sc/source/ui/view/cellsh1.cxx
@@ -1170,7 +1170,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!");
@@ -1229,7 +1229,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 11a16575e36a..6bf344eec654 100644
--- a/sc/source/ui/view/dbfunc3.cxx
+++ b/sc/source/ui/view/dbfunc3.cxx
@@ -68,6 +68,9 @@
 #include <tabvwsh.hxx>
 #include <generalfunction.hxx>
 
+#include <sfx2/lokhelper.hxx>
+#include <comphelper/lok.hxx>
+
 #include <list>
 #include <memory>
 #include <unordered_set>
@@ -98,6 +101,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);
@@ -113,6 +118,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);
@@ -186,7 +193,10 @@ void ScDBFunc::RemoveAllOutlines( bool bRecord )
     bool bOk = aFunc.RemoveAllOutlines( nTab, bRecord );
 
     if (bOk)
+    {
         UpdateScrollBars();
+        ScTabViewShell::notifyAllViewsHeaderInvalidation(BOTH_HEADERS, GetViewData().GetTabNo());
+    }
 }
 
 // auto outlines
@@ -223,6 +233,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();
@@ -2223,4 +2247,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 21b320c5b91a..c5ff3fa47721 100644
--- a/sc/source/ui/view/gridwin.cxx
+++ b/sc/source/ui/view/gridwin.cxx
@@ -5557,8 +5557,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);
+
     tools::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 fd3464a029cc..39e822320ede 100644
--- a/sc/source/ui/view/tabview.cxx
+++ b/sc/source/ui/view/tabview.cxx
@@ -2567,6 +2567,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 tools::Rectangle& rRectangle)
 {
     ScDocument* pDoc = aViewData.GetDocument();
@@ -2625,6 +2767,20 @@ OUString ScTabView::getRowColumnHeaders(const tools::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
 
@@ -2678,15 +2834,27 @@ OUString ScTabView::getRowColumnHeaders(const tools::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;
@@ -2694,10 +2862,13 @@ OUString ScTabView::getRowColumnHeaders(const tools::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
 
 
@@ -2738,6 +2909,19 @@ OUString ScTabView::getRowColumnHeaders(const tools::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
 
@@ -2789,27 +2973,41 @@ OUString ScTabView::getRowColumnHeaders(const tools::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 74b65ef6b4a6..aa72409f84a2 100644
--- a/sc/source/ui/view/tabvwshc.cxx
+++ b/sc/source/ui/view/tabvwshc.cxx
@@ -547,20 +547,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 27e9ad05d738..3d776a0f3301 100644
--- a/sc/source/ui/view/viewfunc.cxx
+++ b/sc/source/ui/view/viewfunc.cxx
@@ -1619,10 +1619,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;
@@ -1694,10 +1694,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
@@ -2295,11 +2295,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)


More information about the Libreoffice-commits mailing list