diff options
author | Jan Holesovsky <kendy@collabora.com> | 2015-04-14 12:05:00 +0200 |
---|---|---|
committer | Jan Holesovsky <kendy@collabora.com> | 2015-04-14 12:16:35 +0200 |
commit | 3f04bfef9e12e947f336aaa441d784f6c77f8e6a (patch) | |
tree | 38f3643711b1a1a65cb2914fb71d0b5a02258ebd /sc | |
parent | 41c8aeabd2537df879e6f1b5c0b57255fd07e2fa (diff) |
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
Diffstat (limited to 'sc')
-rw-r--r-- | sc/source/ui/inc/gridwin.hxx | 8 | ||||
-rw-r--r-- | sc/source/ui/view/gridwin.cxx | 108 |
2 files changed, 107 insertions, 9 deletions
diff --git a/sc/source/ui/inc/gridwin.hxx b/sc/source/ui/inc/gridwin.hxx index 259844ebfd35..0221e601b8ae 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 2b0ca4c85717..838318ecb902 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. |