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

Reply via email to