[Libreoffice-commits] core.git: 3 commits - editeng/source sc/source

Jan Holesovsky kendy at collabora.com
Tue Apr 14 03:18:15 PDT 2015


 editeng/source/editeng/impedit2.cxx |   10 +++
 sc/source/ui/inc/gridwin.hxx        |    8 ++
 sc/source/ui/inc/output.hxx         |    4 +
 sc/source/ui/view/gridwin.cxx       |  108 +++++++++++++++++++++++++++++++++---
 sc/source/ui/view/output2.cxx       |   33 +++++++++--
 5 files changed, 147 insertions(+), 16 deletions(-)

New commits:
commit 771bb58c1c547a874c80d05be59f73cbf68343df
Author: Jan Holesovsky <kendy at collabora.com>
Date:   Tue Apr 14 12:08:39 2015 +0200

    editeng tiled editing: Don't overwrite bInSelection.
    
    Setting bInSelection in MouseButtonUp() feels wrong, and against of its other
    handling elsewhere.  Also it breaks the selection handling in the tiled
    rendering case - on further redraw, selections may disappear.
    
    But it has been so since the initial check-in of the OOo code, so I have no
    idea what corner case I might break by deleting this, so let's guard the
    behavior by isTiledReneding() for now.
    
    Change-Id: I7f7b237f9f0f427e317266e05481bac439c3c8ad

diff --git a/editeng/source/editeng/impedit2.cxx b/editeng/source/editeng/impedit2.cxx
index 7fc5c43..7d4f1c8 100644
--- a/editeng/source/editeng/impedit2.cxx
+++ b/editeng/source/editeng/impedit2.cxx
@@ -567,7 +567,15 @@ bool ImpEditEngine::MouseButtonUp( const MouseEvent& rMEvt, EditView* pView )
 {
     GetSelEngine().SetCurView( pView );
     GetSelEngine().SelMouseButtonUp( rMEvt );
-    bInSelection = false;
+
+    // in the tiled rendering case, setting bInSelection here has unexpected
+    // consequences - further tiles painting removes the selection
+    // FIXME I believe resetting bInSelection should not be here even in the
+    // non-tiled-rendering case, but it has been here since 2000 (and before)
+    // so who knows what corner case it was supposed to solve back then
+    if (!pView->pImpEditView->isTiledRendering())
+        bInSelection = false;
+
     // Special treatments
     EditSelection aCurSel( pView->pImpEditView->GetEditSelection() );
     if ( !aCurSel.HasRange() )
commit 3f04bfef9e12e947f336aaa441d784f6c77f8e6a
Author: Jan Holesovsky <kendy at collabora.com>
Date:   Tue Apr 14 12:05:00 2015 +0200

    sc tiled editing: Implement long-touch to select word in overflowing text.
    
    Normally, the text overflowing from other cells is completely ignored by Calc,
    and the user always works with the underlying cells.
    
    On Android / mobile, it is though more natural to be able to select the text
    directly; so implement a compromise:
    
    * tap places the text cursor, so that the user can write into the
      cells hidden by the text too
    * long-tap selects the word in the text, even if the text 'just' overflows
      from another cell
    
    Change-Id: Ibe8666301ff1df0414c0206c1f3336842485433b

diff --git a/sc/source/ui/inc/gridwin.hxx b/sc/source/ui/inc/gridwin.hxx
index 259844e..0221e60 100644
--- a/sc/source/ui/inc/gridwin.hxx
+++ b/sc/source/ui/inc/gridwin.hxx
@@ -278,6 +278,14 @@ class ScGridWindow : public vcl::Window, public DropTargetHelper, public DragSou
     sal_uInt16          HitPageBreak( const Point& rMouse, ScRange* pSource = NULL,
                                     SCCOLROW* pBreak = NULL, SCCOLROW* pPrev = NULL );
 
+    /** The cell may be covered by text that overflows from a previous cell.
+
+        @return if true, the given cell is covered by (overflowing) text and
+        rTextStartPosX returns the column where the text that overflows
+        starts.
+    */
+    bool            IsCellCoveredByText(SCsCOL nPosX, SCsROW nPosY, SCTAB nTab, SCsCOL &rTextStartPosX);
+
     void            PasteSelection( const Point& rPosPixel );
 
     void            SelectForContextMenu( const Point& rPosPixel, SCsCOL nCellX, SCsROW nCellY );
diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx
index 2b0ca4c..838318e 100644
--- a/sc/source/ui/view/gridwin.cxx
+++ b/sc/source/ui/view/gridwin.cxx
@@ -1657,6 +1657,72 @@ void ScGridWindow::MouseButtonDown( const MouseEvent& rMEvt )
     nNestedButtonState = SC_NESTEDBUTTON_NONE;
 }
 
+bool ScGridWindow::IsCellCoveredByText(SCsCOL nPosX, SCsROW nPosY, SCTAB nTab, SCsCOL &rTextStartPosX)
+{
+    ScDocument* pDoc = pViewData->GetDocument();
+
+    // find the first non-empty cell (this, or to the left)
+    ScRefCellValue aCell;
+    SCsCOL nNonEmptyX = nPosX;
+    for (; nNonEmptyX >= 0; --nNonEmptyX)
+    {
+        aCell.assign(*pDoc, ScAddress(nNonEmptyX, nPosY, nTab));
+        if (!aCell.isEmpty())
+            break;
+    }
+
+    // the inital cell already contains text
+    if (nNonEmptyX == nPosX)
+    {
+        rTextStartPosX = nNonEmptyX;
+        return true;
+    }
+
+    // to the left, there is no cell that would contain (potentially
+    // overrunning) text
+    if (nNonEmptyX < 0 || pDoc->HasAttrib(nNonEmptyX, nPosY, nTab, nPosX, nPosY, nTab, HASATTR_MERGED | HASATTR_OVERLAPPED))
+        return false;
+
+    double nPPTX = pViewData->GetPPTX();
+    double nPPTY = pViewData->GetPPTY();
+
+    ScTableInfo aTabInfo;
+    pDoc->FillInfo(aTabInfo, 0, nPosY, nPosX, nPosY, nTab, nPPTX, nPPTY, false, false);
+
+    Fraction aZoomX = pViewData->GetZoomX();
+    Fraction aZoomY = pViewData->GetZoomY();
+    ScOutputData aOutputData(this, OUTTYPE_WINDOW, aTabInfo, pDoc, nTab,
+            0, 0, 0, nPosY, nPosX, nPosY, nPPTX, nPPTY,
+            &aZoomX, &aZoomY);
+
+    MapMode aCurrentMapMode(GetMapMode());
+    SetMapMode(MAP_PIXEL);
+
+    // obtain the bounding box of the text in first non-empty cell
+    // to the left
+    Rectangle aRect(aOutputData.LayoutStrings(false, false, ScAddress(nNonEmptyX, nPosY, nTab)));
+
+    SetMapMode(aCurrentMapMode);
+
+    // the text does not overrun from the cell
+    if (aRect.IsEmpty())
+        return false;
+
+    SCsCOL nTextEndX;
+    SCsROW nTextEndY;
+
+    // test the rightmost position of the text bounding box
+    long nMiddle = (aRect.Top() + aRect.Bottom()) / 2;
+    pViewData->GetPosFromPixel(aRect.Right(), nMiddle, eWhich, nTextEndX, nTextEndY);
+    if (nTextEndX >= nPosX)
+    {
+        rTextStartPosX = nNonEmptyX;
+        return true;
+    }
+
+    return false;
+}
+
 void ScGridWindow::HandleMouseButtonDown( const MouseEvent& rMEvt, MouseEventState& rState )
 {
     // We have to check if a context menu is shown and we have an UI
@@ -1694,7 +1760,8 @@ void ScGridWindow::HandleMouseButtonDown( const MouseEvent& rMEvt, MouseEventSta
     bool bFormulaMode = pScMod->IsFormulaMode();            // naechster Klick -> Referenz
     bool bEditMode = pViewData->HasEditView(eWhich);        // auch bei Mode==SC_INPUT_TYPE
     bool bDouble = (rMEvt.GetClicks() == 2);
-    bool bIsTiledRendering = pViewData->GetDocument()->GetDrawLayer()->isTiledRendering();
+    ScDocument* pDoc = pViewData->GetDocument();
+    bool bIsTiledRendering = pDoc->GetDrawLayer()->isTiledRendering();
 
     //  DeactivateIP passiert nur noch bei MarkListHasChanged
 
@@ -1704,20 +1771,44 @@ void ScGridWindow::HandleMouseButtonDown( const MouseEvent& rMEvt, MouseEventSta
     if ( !nButtonDown || !bDouble )             // single (first) click is always valid
         nButtonDown = rMEvt.GetButtons();       // set nButtonDown first, so StopMarking works
 
-    // special handling of empty cells with tiled rendering - with double
-    // click, the entire cell is selected
-    if (bIsTiledRendering && bEditMode && bDouble)
+    // special handling of empty cells with tiled rendering
+    if (bIsTiledRendering)
     {
-        Point aPos = rMEvt.GetPosPixel();
-        SCsCOL nPosX;
+        Point aPos(rMEvt.GetPosPixel());
+        SCsCOL nPosX, nNonEmptyX;
         SCsROW nPosY;
         SCTAB nTab = pViewData->GetTabNo();
         pViewData->GetPosFromPixel(aPos.X(), aPos.Y(), eWhich, nPosX, nPosY);
 
         ScRefCellValue aCell;
-        aCell.assign(*pViewData->GetDocument(), ScAddress(nPosX, nPosY, nTab));
-        if (aCell.isEmpty())
+        aCell.assign(*pDoc, ScAddress(nPosX, nPosY, nTab));
+        bool bIsEmpty = aCell.isEmpty();
+        bool bIsCoveredByText = bIsEmpty && IsCellCoveredByText(nPosX, nPosY, nTab, nNonEmptyX);
+
+        if (bIsCoveredByText)
+        {
+            // if there's any text flowing to this cell, activate the
+            // editengine, so that the text actually gets the events
+            if (bDouble)
+            {
+                ScViewFunc* pView = pViewData->GetView();
+
+                pView->SetCursor(nNonEmptyX, nPosY);
+                SC_MOD()->SetInputMode(SC_INPUT_TABLE);
+
+                bEditMode = pViewData->HasEditView(eWhich);
+                assert(bEditMode);
+
+                // synthesize the 1st click
+                EditView* pEditView = pViewData->GetEditView(eWhich);
+                MouseEvent aEditEvt(rMEvt.GetPosPixel(), 1, MouseEventModifiers::SYNTHETIC, MOUSE_LEFT, 0);
+                pEditView->MouseButtonDown(aEditEvt);
+                pEditView->MouseButtonUp(aEditEvt);
+            }
+        }
+        else if (bIsEmpty && bEditMode && bDouble)
         {
+            // double-click in an empty cell: the entire cell is selected
             SetCellSelectionPixel(LOK_SETTEXTSELECTION_START, aPos.X(), aPos.Y());
             SetCellSelectionPixel(LOK_SETTEXTSELECTION_END, aPos.X(), aPos.Y());
             return;
@@ -1865,7 +1956,6 @@ void ScGridWindow::HandleMouseButtonDown( const MouseEvent& rMEvt, MouseEventSta
     SCsROW nPosY;
     pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
     SCTAB nTab = pViewData->GetTabNo();
-    ScDocument* pDoc = pViewData->GetDocument();
 
     // Auto filter / pivot table / data select popup.  This shouldn't activate the part.
 
commit 41c8aeabd2537df879e6f1b5c0b57255fd07e2fa
Author: Jan Holesovsky <kendy at collabora.com>
Date:   Tue Apr 14 11:59:56 2015 +0200

    sc tiled editing: Re-purposed DrawStrings().
    
    Calc has no real understanding whether there is a text overflowing to the
    other cells or not, it is sorted out when drawing in DrawStrings().
    
    Re-purpose it so that it has a mode where the caller can ask for actual region
    of text that covers the given cell.
    
    Change-Id: Id0caa3972727bafdaeb148f8bbabb412f771a67d

diff --git a/sc/source/ui/inc/output.hxx b/sc/source/ui/inc/output.hxx
index d9e1a46..7d8ef81 100644
--- a/sc/source/ui/inc/output.hxx
+++ b/sc/source/ui/inc/output.hxx
@@ -299,6 +299,10 @@ public:
 
     void    DrawGrid( bool bGrid, bool bPage );
     void    DrawStrings( bool bPixelToLogic = false );
+
+    /// Draw all strings, or provide Rectangle where the text (defined by rAddress) would be drawn.
+    Rectangle LayoutStrings(bool bPixelToLogic = false, bool bPaint = true, const ScAddress &rAddress = ScAddress());
+
     void    DrawDocumentBackground();
     void    DrawBackground();
     void    DrawShadow();
diff --git a/sc/source/ui/view/output2.cxx b/sc/source/ui/view/output2.cxx
index e33a747..6ffe033 100644
--- a/sc/source/ui/view/output2.cxx
+++ b/sc/source/ui/view/output2.cxx
@@ -1426,9 +1426,14 @@ static SvxCellHorJustify getAlignmentFromContext( SvxCellHorJustify eInHorJust,
 
 void ScOutputData::DrawStrings( bool bPixelToLogic )
 {
+    LayoutStrings(bPixelToLogic, true);
+}
+
+Rectangle ScOutputData::LayoutStrings(bool bPixelToLogic, bool bPaint, const ScAddress &rAddress)
+{
     OSL_ENSURE( mpDev == mpRefDevice ||
                 mpDev->GetMapMode().GetMapUnit() == mpRefDevice->GetMapMode().GetMapUnit(),
-                "DrawStrings: unterschiedliche MapUnits ?!?!" );
+                "LayoutStrings: unterschiedliche MapUnits ?!?!" );
 
     vcl::PDFExtOutDevData* pPDFData = PTR_CAST( vcl::PDFExtOutDevData, mpDev->GetExtOutDevData() );
 
@@ -1469,9 +1474,9 @@ void ScOutputData::DrawStrings( bool bPixelToLogic )
     for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
     {
         RowInfo* pThisRowInfo = &pRowInfo[nArrY];
-        if ( pThisRowInfo->bChanged )
+        SCROW nY = pThisRowInfo->nRowNo;
+        if ((bPaint && pThisRowInfo->bChanged) || (!bPaint && rAddress.Row() == nY))
         {
-            SCROW nY = pThisRowInfo->nRowNo;
             long nPosX = nInitPosX;
             if ( nLoopStartX < nX1 )
                 nPosX -= pRowInfo[0].pCellInfo[nLoopStartX+1].nWidth * nLayoutSign;
@@ -2041,6 +2046,16 @@ void ScOutputData::DrawStrings( bool bPixelToLogic )
                                 }
                             }
 
+                            // if we are not painting, it means we are interested in
+                            // the area of the text that covers the specified cell
+                            if (!bPaint && rAddress.Col() == nX)
+                            {
+                                Rectangle aRect;
+                                mpDev->GetTextBoundRect(aRect, aShort);
+                                aRect += aDrawTextPos;
+                                return aRect;
+                            }
+
                             if (bMetaFile || pFmtDevice != mpDev || aZoomX != aZoomY)
                             {
                                 size_t nLen = aShort.getLength();
@@ -2057,10 +2072,14 @@ void ScOutputData::DrawStrings( bool bPixelToLogic )
                                         aDX[i] = static_cast<sal_Int32>(aDX[i] / fMul + 0.5);
                                 }
 
-                                mpDev->DrawTextArray(aDrawTextPos, aShort, &aDX[0]);
+                                if (bPaint)
+                                    mpDev->DrawTextArray(aDrawTextPos, aShort, &aDX[0]);
                             }
                             else
-                                mpDev->DrawText(aDrawTextPos, aShort);
+                            {
+                                if (bPaint)
+                                    mpDev->DrawText(aDrawTextPos, aShort);
+                            }
                         }
 
                         if ( bHClip || bVClip )
@@ -2073,7 +2092,7 @@ void ScOutputData::DrawStrings( bool bPixelToLogic )
 
                         // PDF: whole-cell hyperlink from formula?
                         bool bHasURL = pPDFData && aCell.meType == CELLTYPE_FORMULA && aCell.mpFormula->IsHyperLinkCell();
-                        if ( bHasURL )
+                        if (bPaint && bHasURL)
                         {
                             Rectangle aURLRect( aURLStart, aVars.GetTextSize() );
                             lcl_DoHyperlinkResult(mpDev, aURLRect, aCell);
@@ -2087,6 +2106,8 @@ void ScOutputData::DrawStrings( bool bPixelToLogic )
     }
     if ( bProgress )
         ScProgress::DeleteInterpretProgress();
+
+    return Rectangle();
 }
 
 ScFieldEditEngine* ScOutputData::CreateOutputEditEngine()


More information about the Libreoffice-commits mailing list