diff options
author | Kohei Yoshida <kohei.yoshida@collabora.com> | 2014-04-11 23:07:49 -0400 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@collabora.com> | 2014-04-11 23:09:38 -0400 |
commit | cd22c3442389f69fc1cc14dd07b17f5a59498e5e (patch) | |
tree | 63ee9035e0a3008584fc9c407d0b1c71ad53debd /sc | |
parent | cf1d4c02c14772824a7149957fa119c6e290640b (diff) |
fdo#74087: Inspect if a mis-spelled word is at cursor position...
then decide whether to launch a spell candidate menu or a regular context
menu.
Change-Id: Ib121e9c6729e068c70ff216391f863639aa01951
Diffstat (limited to 'sc')
-rw-r--r-- | sc/source/ui/inc/gridwin.hxx | 2 | ||||
-rw-r--r-- | sc/source/ui/view/gridwin.cxx | 180 |
2 files changed, 146 insertions, 36 deletions
diff --git a/sc/source/ui/inc/gridwin.hxx b/sc/source/ui/inc/gridwin.hxx index 92743039a1e4..59cb57b22726 100644 --- a/sc/source/ui/inc/gridwin.hxx +++ b/sc/source/ui/inc/gridwin.hxx @@ -271,6 +271,8 @@ class ScGridWindow : public Window, public DropTargetHelper, public DragSourceHe bool GetEditUrl( const Point& rPos, OUString* pName=0, OUString* pUrl=0, OUString* pTarget=0 ); + bool IsSpellErrorAtPos( const Point& rPos, SCCOL nCol1, SCCOL nCol2, SCROW nRow ); + bool HitRangeFinder( const Point& rMouse, RfCorner& rCorner, sal_uInt16* pIndex = NULL, SCsCOL* pAddX = NULL, SCsROW* pAddY = NULL ); diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx index 5f3764e7c557..8a47818fe6dd 100644 --- a/sc/source/ui/view/gridwin.cxx +++ b/sc/source/ui/view/gridwin.cxx @@ -136,6 +136,7 @@ #include <vector> #include <boost/scoped_ptr.hpp> +#include <boost/shared_ptr.hpp> using namespace com::sun::star; using ::com::sun::star::uno::Sequence; @@ -2940,6 +2941,10 @@ void ScGridWindow::Command( const CommandEvent& rCEvt ) SCsROW nCellY = -1; pViewData->GetPosFromPixel(aPosPixel.X(), aPosPixel.Y(), eWhich, nCellX, nCellY); + bool bSpellError = false; + SCCOL nColSpellError = nCellX; + ScRefCellValue aSpellCheckCell; + if ( bMouse ) { ScDocument* pDoc = pViewData->GetDocument(); @@ -2962,14 +2967,39 @@ void ScGridWindow::Command( const CommandEvent& rCEvt ) // Selecting this cell is not allowed, neither is context menu. return; + if (mpSpellCheckCxt) + { + // Find the first string to the left for spell checking in case the current cell is empty. + ScAddress aPos(nCellX, nCellY, nTab); + aSpellCheckCell.assign(*pDoc, aPos); + while (aSpellCheckCell.meType == CELLTYPE_NONE) + { + // Loop until we get the first non-empty cell in the row. + aPos.IncCol(-1); + if (aPos.Col() < 0) + break; + + aSpellCheckCell.assign(*pDoc, aPos); + } + + if (aPos.Col() >= 0 && (aSpellCheckCell.meType == CELLTYPE_STRING || aSpellCheckCell.meType == CELLTYPE_EDIT)) + nColSpellError = aPos.Col(); + + bSpellError = (mpSpellCheckCxt->isMisspelled(nColSpellError, nCellY)); + if (bSpellError) + { + // Check and see if a misspelled word is under the mouse pointer. + bSpellError = IsSpellErrorAtPos(aPosPixel, nColSpellError, nCellX, nCellY); + } + } + // #i18735# First select the item under the mouse pointer. // This can change the selection, and the view state (edit mode, etc). - SelectForContextMenu( aPosPixel, nCellX, nCellY ); + SelectForContextMenu(aPosPixel, bSpellError ? nColSpellError : nCellX, nCellY); } - sal_Bool bDone = false; - sal_Bool bEdit = pViewData->HasEditView(eWhich); - bool bSpellError = (mpSpellCheckCxt && mpSpellCheckCxt->isMisspelled(nCellX, nCellY)); + bool bDone = false; + bool bEdit = pViewData->HasEditView(eWhich); if ( !bEdit ) { @@ -5091,6 +5121,54 @@ void ScGridWindow::RFMouseMove( const MouseEvent& rMEvt, bool bUp ) pViewData->GetView()->ResetTimer(); } +namespace { + +SvxAdjust toSvxAdjust( const ScPatternAttr& rPat ) +{ + SvxCellHorJustify eHorJust = + static_cast<SvxCellHorJustify>( + static_cast<const SvxHorJustifyItem&>(rPat.GetItem(ATTR_HOR_JUSTIFY)).GetValue()); + + SvxAdjust eSvxAdjust = SVX_ADJUST_LEFT; + switch (eHorJust) + { + case SVX_HOR_JUSTIFY_LEFT: + case SVX_HOR_JUSTIFY_REPEAT: // nicht implementiert + case SVX_HOR_JUSTIFY_STANDARD: // always Text if an EditCell type + eSvxAdjust = SVX_ADJUST_LEFT; + break; + case SVX_HOR_JUSTIFY_RIGHT: + eSvxAdjust = SVX_ADJUST_RIGHT; + break; + case SVX_HOR_JUSTIFY_CENTER: + eSvxAdjust = SVX_ADJUST_CENTER; + break; + case SVX_HOR_JUSTIFY_BLOCK: + eSvxAdjust = SVX_ADJUST_BLOCK; + break; + } + + return eSvxAdjust; +} + +boost::shared_ptr<ScFieldEditEngine> createEditEngine( ScDocShell* pDocSh, const ScPatternAttr& rPat ) +{ + ScDocument* pDoc = pDocSh->GetDocument(); + + boost::shared_ptr<ScFieldEditEngine> pEngine(new ScFieldEditEngine(pDoc, pDoc->GetEditPool())); + ScSizeDeviceProvider aProv(pDocSh); + pEngine->SetRefDevice(aProv.GetDevice()); + pEngine->SetRefMapMode(MAP_100TH_MM); + SfxItemSet aDefault = pEngine->GetEmptyItemSet(); + rPat.FillEditItemSet(&aDefault); + aDefault.Put( SvxAdjustItem(toSvxAdjust(rPat), EE_PARA_JUST) ); + pEngine->SetDefaults(aDefault); + + return pEngine; +} + +} + bool ScGridWindow::GetEditUrl( const Point& rPos, OUString* pName, OUString* pUrl, OUString* pTarget ) { @@ -5127,32 +5205,7 @@ bool ScGridWindow::GetEditUrl( const Point& rPos, // EditEngine - ScFieldEditEngine aEngine(pDoc, pDoc->GetEditPool()); - ScSizeDeviceProvider aProv(pDocSh); - aEngine.SetRefDevice( aProv.GetDevice() ); - aEngine.SetRefMapMode( MAP_100TH_MM ); - SfxItemSet aDefault( aEngine.GetEmptyItemSet() ); - pPattern->FillEditItemSet( &aDefault ); - SvxAdjust eSvxAdjust = SVX_ADJUST_LEFT; - switch (eHorJust) - { - case SVX_HOR_JUSTIFY_LEFT: - case SVX_HOR_JUSTIFY_REPEAT: // nicht implementiert - case SVX_HOR_JUSTIFY_STANDARD: // always Text if an EditCell type - eSvxAdjust = SVX_ADJUST_LEFT; - break; - case SVX_HOR_JUSTIFY_RIGHT: - eSvxAdjust = SVX_ADJUST_RIGHT; - break; - case SVX_HOR_JUSTIFY_CENTER: - eSvxAdjust = SVX_ADJUST_CENTER; - break; - case SVX_HOR_JUSTIFY_BLOCK: - eSvxAdjust = SVX_ADJUST_BLOCK; - break; - } - aDefault.Put( SvxAdjustItem( eSvxAdjust, EE_PARA_JUST ) ); - aEngine.SetDefaults( aDefault ); + boost::shared_ptr<ScFieldEditEngine> pEngine = createEditEngine(pDocSh, *pPattern); MapMode aEditMode = pViewData->GetLogicMode(eWhich); // ohne Drawing-Skalierung Rectangle aLogicEdit = PixelToLogic( aEditRect, aEditMode ); @@ -5169,13 +5222,13 @@ bool ScGridWindow::GetEditUrl( const Point& rPos, if (bBreak) aPaperSize.Width() = nThisColLogic; - aEngine.SetPaperSize( aPaperSize ); + pEngine->SetPaperSize( aPaperSize ); boost::scoped_ptr<EditTextObject> pTextObj; if (aCell.meType == CELLTYPE_EDIT) { if (aCell.mpEditText) - aEngine.SetText(*aCell.mpEditText); + pEngine->SetText(*aCell.mpEditText); } else // Not an Edit cell and is a formula cell with 'Hyperlink' // function if we have no URL, otherwise it could be a formula @@ -5187,13 +5240,13 @@ bool ScGridWindow::GetEditUrl( const Point& rPos, pTextObj.reset(ScEditUtil::CreateURLObjectFromURL(*pDoc, sURL, sURL)); if (pTextObj.get()) - aEngine.SetText(*pTextObj); + pEngine->SetText(*pTextObj); } long nStartX = aLogicEdit.Left(); - long nTextWidth = aEngine.CalcTextWidth(); - long nTextHeight = aEngine.GetTextHeight(); + long nTextWidth = pEngine->CalcTextWidth(); + long nTextHeight = pEngine->GetTextHeight(); if ( nTextWidth < nThisColLogic ) { if (eHorJust == SVX_HOR_JUSTIFY_RIGHT) @@ -5221,7 +5274,7 @@ bool ScGridWindow::GetEditUrl( const Point& rPos, Point aLogicClick = PixelToLogic(rPos,aEditMode); if ( aLogicEdit.IsInside(aLogicClick) ) { - EditView aTempView( &aEngine, this ); + EditView aTempView(pEngine.get(), this); aTempView.SetOutputArea( aLogicEdit ); sal_Bool bRet = false; @@ -5255,6 +5308,61 @@ bool ScGridWindow::GetEditUrl( const Point& rPos, return false; } +bool ScGridWindow::IsSpellErrorAtPos( const Point& rPos, SCCOL nCol1, SCCOL nCol2, SCROW nRow ) +{ + if (!mpSpellCheckCxt) + return false; + + SCTAB nTab = pViewData->GetTabNo(); + ScDocShell* pDocSh = pViewData->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + + ScAddress aCellPos(nCol1, nRow, nTab); + ScRefCellValue aCell; + aCell.assign(*pDoc, aCellPos); + if (aCell.meType != CELLTYPE_STRING && aCell.meType != CELLTYPE_EDIT) + return false; + + const std::vector<editeng::MisspellRanges>* pRanges = mpSpellCheckCxt->getMisspellRanges(nCol1, nRow); + if (!pRanges) + return false; + + const ScPatternAttr* pPattern = pDoc->GetPattern(nCol1, nRow, nTab); + + Rectangle aEditRect = pViewData->GetEditArea(eWhich, nCol1, nRow, this, pPattern, false); + if (rPos.Y() < aEditRect.Top()) + return false; + + Rectangle aEditRect2 = pViewData->GetEditArea(eWhich, nCol2, nRow, this, pPattern, false); + long nExt = aEditRect2.Left() - aEditRect.Right() + aEditRect2.GetWidth(); + aEditRect.setWidth(aEditRect.getWidth() + nExt); + + MapMode aEditMode = pViewData->GetLogicMode(eWhich); + Rectangle aLogicEdit = PixelToLogic(aEditRect, aEditMode); + Point aLogicClick = PixelToLogic(rPos, aEditMode); + + if (!aLogicEdit.IsInside(aLogicClick)) + return false; + + boost::shared_ptr<ScFieldEditEngine> pEngine = createEditEngine(pDocSh, *pPattern); + + Size aPaperSize = Size(1000000, 1000000); + pEngine->SetPaperSize(aPaperSize); + + if (aCell.meType == CELLTYPE_EDIT) + pEngine->SetText(*aCell.mpEditText); + else + pEngine->SetText(aCell.mpString->getString()); + + pEngine->SetControlWord(pEngine->GetControlWord() | EE_CNTRL_ONLINESPELLING); + pEngine->SetAllMisspellRanges(*pRanges); + + EditView aTempView(pEngine.get(), this); + aTempView.SetOutputArea(aLogicEdit); + + return aTempView.IsWrongSpelledWordAtPos(rPos); +} + bool ScGridWindow::HasScenarioButton( const Point& rPosPixel, ScRange& rScenRange ) { ScDocument* pDoc = pViewData->GetDocument(); |