summaryrefslogtreecommitdiff
path: root/sc/source
diff options
context:
space:
mode:
authorJan Holesovsky <kendy@collabora.com>2015-04-14 12:05:00 +0200
committerJan Holesovsky <kendy@collabora.com>2015-04-14 12:16:35 +0200
commit3f04bfef9e12e947f336aaa441d784f6c77f8e6a (patch)
tree38f3643711b1a1a65cb2914fb71d0b5a02258ebd /sc/source
parent41c8aeabd2537df879e6f1b5c0b57255fd07e2fa (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/source')
-rw-r--r--sc/source/ui/inc/gridwin.hxx8
-rw-r--r--sc/source/ui/view/gridwin.cxx108
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.