diff options
-rw-r--r-- | compilerplugins/clang/badstatics.cxx | 3 | ||||
-rw-r--r-- | editeng/source/editeng/editview.cxx | 4 | ||||
-rw-r--r-- | include/sfx2/lokhelper.hxx | 18 | ||||
-rw-r--r-- | sc/source/ui/view/gridwin4.cxx | 475 | ||||
-rw-r--r-- | sc/source/ui/view/viewdata.cxx | 2 | ||||
-rw-r--r-- | sfx2/source/view/lokhelper.cxx | 78 |
6 files changed, 298 insertions, 282 deletions
diff --git a/compilerplugins/clang/badstatics.cxx b/compilerplugins/clang/badstatics.cxx index 18638695bbeb..1d003acdb8a6 100644 --- a/compilerplugins/clang/badstatics.cxx +++ b/compilerplugins/clang/badstatics.cxx @@ -233,6 +233,9 @@ public: // AquaA11yFocusTracker::m_aDocumentWindowList elements symmetrically added and // removed in AquaA11yFocusTracker::window_got_focus and // AquaA11yFocusTracker::WindowEventHandler (TODO: is that guaranteed?) + || (loplugin::DeclCheck(pVarDecl).Var("maEditViewHistory") + .Class("LOKEditViewHistory").GlobalNamespace()) + // sfx2/lokhelper.hxx, only handling pointers, not owning ) // these variables appear unproblematic { return true; diff --git a/editeng/source/editeng/editview.cxx b/editeng/source/editeng/editview.cxx index e08c3c81d77d..9868c3ebec59 100644 --- a/editeng/source/editeng/editview.cxx +++ b/editeng/source/editeng/editview.cxx @@ -60,6 +60,7 @@ #include <LibreOfficeKit/LibreOfficeKitEnums.h> #include <comphelper/lok.hxx> #include <sfx2/viewsh.hxx> +#include <sfx2/lokhelper.hxx> #include <osl/diagnose.h> #include <boost/property_tree/json_parser.hpp> @@ -208,6 +209,7 @@ tools::Rectangle lcl_negateRectX(const tools::Rectangle& rRect) void EditView::InvalidateWindow(const tools::Rectangle& rClipRect) { + LOKEditViewHistory::Update(); bool bNegativeX = IsNegativeX(); if (EditViewCallbacks* pEditViewCallbacks = getImpl().getEditViewCallbacks()) { @@ -243,6 +245,8 @@ void EditView::InvalidateOtherViewWindows( const tools::Rectangle& rInvRect ) void EditView::Invalidate() { const tools::Rectangle& rInvRect = GetInvalidateRect(); + + LOKEditViewHistory::Update(); getImpl().InvalidateAtWindow(rInvRect); InvalidateOtherViewWindows(rInvRect); } diff --git a/include/sfx2/lokhelper.hxx b/include/sfx2/lokhelper.hxx index f87bbd70cd36..c4e88035fd96 100644 --- a/include/sfx2/lokhelper.hxx +++ b/include/sfx2/lokhelper.hxx @@ -23,8 +23,10 @@ #include <cstddef> #include <rtl/strbuf.hxx> #include <rtl/string.hxx> +#include <list> #include <optional> #include <string_view> +#include <unordered_map> #define LOK_NOTIFY_LOG_TO_CLIENT 1 @@ -261,6 +263,22 @@ public: ~SfxLokLanguageGuard(); }; +typedef std::list<SfxViewShell*> ViewShellList; + +/// Used to keep track of the last N views that text edited a document through an EditView +class SFX2_DLLPUBLIC LOKEditViewHistory +{ +public: + typedef std::list<SfxViewShell*> ViewShellList; + typedef std::unordered_map<int, ViewShellList> EditViewHistoryMap; + + static void Update(bool bRemove = false); + static ViewShellList GetHistoryForDoc(ViewShellDocId aDocId); + static ViewShellList GetSortedViewsForDoc(ViewShellDocId aDocId); +private: + static EditViewHistoryMap maEditViewHistory; +}; + #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/view/gridwin4.cxx b/sc/source/ui/view/gridwin4.cxx index 344d99b26cef..e9be15580668 100644 --- a/sc/source/ui/view/gridwin4.cxx +++ b/sc/source/ui/view/gridwin4.cxx @@ -280,26 +280,6 @@ static void lcl_DrawHighlight( ScOutputData& rOutputData, const ScViewData& rVie } } -// Calculates top-left offset to be applied based on margins and indent. -static void lcl_GetEditAreaTLOffset(tools::Long& nOffsetX, tools::Long& nOffsetY, const ScAddress& rAddr, - const ScViewData& rViewData, ScDocument& rDoc) -{ - tools::Long nLeftMargin = 0; - tools::Long nTopMargin = 0; - tools::Long nIndent = 0; - tools::Long nDummy = 0; - ScEditUtil aEUtil(&rDoc, rAddr.Col(), rAddr.Row(), rAddr.Tab(), - Point(0, 0), nullptr, rViewData.GetPPTX(), - rViewData.GetPPTY(), Fraction(1.0), Fraction(1.0), - false /* bPrintTwips */); - const ScPatternAttr* pPattern = rDoc.GetPattern(rAddr); - if (!rDoc.IsLayoutRTL(rAddr.Tab())) - nIndent = aEUtil.GetIndent(pPattern); - aEUtil.GetMargins(pPattern, nLeftMargin, nTopMargin, nDummy, nDummy); - nOffsetX = nIndent + nLeftMargin; - nOffsetY = nTopMargin; -} - void ScGridWindow::DoInvertRect( const tools::Rectangle& rPixel ) { if ( rPixel == aInvertRect ) @@ -656,24 +636,27 @@ private: namespace { -int lcl_GetMultiLineHeight(EditEngine& rEditEngine) +tools::Rectangle lcl_negateRectX(const tools::Rectangle& rRect) { - int nHeight = 0; - int nParagraphs = rEditEngine.GetParagraphCount(); - if (nParagraphs > 1 || (nParagraphs > 0 && rEditEngine.GetLineCount(0) > 1)) - { - for (int nPara = 0; nPara < nParagraphs; nPara++) - { - nHeight += rEditEngine.GetLineCount(nPara) * rEditEngine.GetLineHeight(nPara); - } - } + return {-rRect.Right(), rRect.Top(), -rRect.Left(), rRect.Bottom()}; +} - return nHeight; +tools::Long GetSide(const tools::Rectangle& rRect, int i) +{ + static decltype(&tools::Rectangle::Left) GetSides[4] = { + &tools::Rectangle::Left, &tools::Rectangle::Top, + &tools::Rectangle::Right, &tools::Rectangle::Bottom + }; + return (rRect.*GetSides[i])(); } -tools::Rectangle lcl_negateRectX(const tools::Rectangle& rRect) +Fraction GetZoom(const ScViewData& rViewData, int i) { - return tools::Rectangle(-rRect.Right(), rRect.Top(), -rRect.Left(), rRect.Bottom()); + static decltype(&ScViewData::GetZoomX) GetZooms[4] = { + &ScViewData::GetZoomX, &ScViewData::GetZoomY, + &ScViewData::GetZoomX, &ScViewData::GetZoomY + }; + return (rViewData.*GetZooms[i])(); } } @@ -1095,183 +1078,195 @@ void ScGridWindow::DrawContent(OutputDevice &rDevice, const ScTableInfo& rTableI } } - // paint in-place editing + // in place editing - lok case if (bIsTiledRendering) { ScTabViewShell* pThisViewShell = mrViewData.GetViewShell(); - SfxViewShell* pViewShell = SfxViewShell::GetFirst(); + ViewShellList aCurrentDocViewList = LOKEditViewHistory::GetSortedViewsForDoc(pThisViewShell->GetDocId()); + tools::Rectangle aTileRectPx(Point(nScrX, nScrY), Size(aOutputData.GetScrW(), aOutputData.GetScrH())); - while (pViewShell) + for (SfxViewShell* pVS: aCurrentDocViewList) { - bool bEnterLoop = bIsTiledRendering || pViewShell != pThisViewShell; - if (bEnterLoop && pViewShell->GetDocId() == pThisViewShell->GetDocId()) + auto pTabViewShell = dynamic_cast<ScTabViewShell*>(pVS); + if (!pTabViewShell) + continue; + + ScViewData& rOtherViewData = pTabViewShell->GetViewData(); + ScSplitPos eOtherWhich = rOtherViewData.GetEditActivePart(); + + bool bOtherEditMode = rOtherViewData.HasEditView(eOtherWhich); + SCCOL nCol1 = rOtherViewData.GetEditStartCol(); + SCROW nRow1 = rOtherViewData.GetEditStartRow(); + SCCOL nCol2 = rOtherViewData.GetEditEndCol(); + SCROW nRow2 = rOtherViewData.GetEditEndRow(); + + if (!(bOtherEditMode + && ( nCol2 >= nX1 && nCol1 <= nX2 && nRow2 >= nY1 && nRow1 <= nY2 ) + && rOtherViewData.GetRefTabNo() == nTab)) + continue; // only views where in place editing is occurring need to be rendered + + EditView* pOtherEditView = rOtherViewData.GetEditView(eOtherWhich); + if (!pOtherEditView) + continue; + + rDevice.SetLineColor(); + // Theme colors + const ScPatternAttr* pPattern = rDoc.GetPattern( nCol1, nRow1, nTab ); + Color aCellColor = pPattern->GetItem(ATTR_BACKGROUND).GetColor(); + if (aCellColor.IsTransparent()) { - ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(pViewShell); - if (pTabViewShell) - { - ScViewData& rOtherViewData = pTabViewShell->GetViewData(); - ScSplitPos eOtherWhich = rOtherViewData.GetEditActivePart(); - - bool bOtherEditMode = rOtherViewData.HasEditView(eOtherWhich); - SCCOL nCol1 = rOtherViewData.GetEditStartCol(); - SCROW nRow1 = rOtherViewData.GetEditStartRow(); - SCCOL nCol2 = rOtherViewData.GetEditEndCol(); - SCROW nRow2 = rOtherViewData.GetEditEndRow(); - bOtherEditMode = bOtherEditMode - && ( nCol2 >= nX1 && nCol1 <= nX2 && nRow2 >= nY1 && nRow1 <= nY2 ); - if (bOtherEditMode && rOtherViewData.GetRefTabNo() == nTab) - { - EditView* pOtherEditView = rOtherViewData.GetEditView(eOtherWhich); - if (pOtherEditView) - { - tools::Long nScreenX = aOutputData.nScrX; - tools::Long nScreenY = aOutputData.nScrY; + const ScViewRenderingOptions& rViewRenderingOptions = pTabViewShell->GetViewRenderingData(); + aCellColor = rViewRenderingOptions.GetDocColor(); + } + rDevice.SetFillColor(aCellColor); + pOtherEditView->SetBackgroundColor(aCellColor); + + // edit rectangle / background + Point aStart = mrViewData.GetScrPos( nCol1, nRow1, eOtherWhich ); + Point aEnd = mrViewData.GetScrPos( nCol2+1, nRow2+1, eOtherWhich ); + tools::Rectangle aEditRectPx(aStart, aEnd); + if (bLokRTL) + { + // Transform the cell range X coordinates such that the edit cell area is + // horizontally mirrored w.r.t the (combined-)tile. + aStart.setX(pLokRTLCtxt->docToTilePos(aStart.X())); + aEnd.setX(pLokRTLCtxt->docToTilePos(aEnd.X())); + } - rDevice.SetLineColor(); - SfxViewShell* pSfxViewShell = SfxViewShell::Current(); - ScTabViewShell* pCurrentViewShell = dynamic_cast<ScTabViewShell*>(pSfxViewShell); - if (pCurrentViewShell) - { - const ScPatternAttr* pPattern = rDoc.GetPattern( nCol1, nRow1, nTab ); - Color aCellColor = pPattern->GetItem(ATTR_BACKGROUND).GetColor(); - if (aCellColor.IsTransparent()) - { - const ScViewRenderingOptions& rViewRenderingOptions = pCurrentViewShell->GetViewRenderingData(); - aCellColor = rViewRenderingOptions.GetDocColor(); - } - rDevice.SetFillColor(aCellColor); - pOtherEditView->SetBackgroundColor(aCellColor); - } - Point aStart = mrViewData.GetScrPos( nCol1, nRow1, eOtherWhich ); - Point aEnd = mrViewData.GetScrPos( nCol2+1, nRow2+1, eOtherWhich ); + // don't overwrite grid + tools::Long nLayoutSign = bLayoutRTL ? -1 : 1; + aEnd.AdjustX( -(2 * nLayoutSign) ); + aEnd.AdjustY( -2 ); - if (bIsTiledRendering) - { - EditEngine& rEditEngine = pOtherEditView->getEditEngine(); - aEnd.AdjustY(lcl_GetMultiLineHeight(rEditEngine)); - } + tools::Rectangle aBackground(aStart, aEnd); + if (bLokRTL) + aBackground.Normalize(); + tools::Rectangle aBGAbs(aBackground); - if (bLokRTL) - { - // Transform the cell range X coordinates such that the edit cell area is - // horizontally mirrored w.r.t the (combined-)tile. - aStart.setX(pLokRTLCtxt->docToTilePos(aStart.X())); - aEnd.setX(pLokRTLCtxt->docToTilePos(aEnd.X())); - } + // Need to draw the background in absolute coords. + Point aOriginTw = aOriginalMode.GetOrigin(); + Point aOriginPx = o3tl::convert(aOriginTw, o3tl::Length::twip, o3tl::Length::px); + Point aOriginAbsPx = aOriginPx + aTileRectPx.GetPos(); + aBackground += aOriginAbsPx; + rDevice.SetMapMode(aDrawMode); - // don't overwrite grid - tools::Long nLayoutSign = bLayoutRTL ? -1 : 1; - aEnd.AdjustX( -(2 * nLayoutSign) ); - aEnd.AdjustY( -2 ); - - tools::Rectangle aBackground(aStart, aEnd); - if (bLokRTL) - aBackground.Normalize(); - - // Need to draw the background in absolute coords. - Point aOrigin = aOriginalMode.GetOrigin(); - aOrigin.setX( - o3tl::convert(aOrigin.getX(), o3tl::Length::twip, o3tl::Length::px) - + nScreenX); - aOrigin.setY( - o3tl::convert(aOrigin.getY(), o3tl::Length::twip, o3tl::Length::px) - + nScreenY); - aBackground += aOrigin; - rDevice.SetMapMode(aDrawMode); - - static const double twipFactor = 15 * 1.76388889; // 26.45833335 - // keep into account the zoom factor - aOrigin = Point((aOrigin.getX() * twipFactor) / static_cast<double>(aDrawMode.GetScaleX()), - (aOrigin.getY() * twipFactor) / static_cast<double>(aDrawMode.GetScaleY())); - - MapMode aNew = rDevice.GetMapMode(); - aNew.SetOrigin(aOrigin); - rDevice.SetMapMode(aNew); - - // paint the background - rDevice.DrawRect(rDevice.PixelToLogic(aBackground)); - tools::Rectangle aBGAbs(aBackground); - - tools::Rectangle aEditRect(aBackground); - tools::Long nOffsetX = 0, nOffsetY = 0; - // Get top-left offset because of margin and indent. - lcl_GetEditAreaTLOffset(nOffsetX, nOffsetY, ScAddress(nCol1, nRow1, nTab), mrViewData, rDoc); - aEditRect.AdjustLeft(nOffsetX + 1); - aEditRect.AdjustRight(1); - aEditRect.AdjustTop(nOffsetY + 1); - aEditRect.AdjustBottom(1); - - // EditView has an 'output area' which is used to clip the 'paint area' we provide below. - // So they need to be in the same coordinates/units. This is tied to the mapmode of the gridwin - // attached to the EditView, so we have to change its mapmode too (temporarily). We save the - // original mapmode and 'output area' and roll them back when we finish painting to rDevice. - OutputDevice& rOtherWin = pOtherEditView->GetOutputDevice(); - const tools::Rectangle aOrigOutputArea(pOtherEditView->GetOutputArea()); // Not in pixels. - const MapMode aOrigMapMode = rOtherWin.GetMapMode(); - rOtherWin.SetMapMode(rDevice.GetMapMode()); - - // Avoid sending wrong cursor/selection messages by the 'other' view, as the output-area is going - // to be tweaked temporarily to match the current view's zoom. - SuppressEditViewMessagesGuard aGuard(*pOtherEditView); - comphelper::ScopeGuard aOutputGuard( - [pOtherEditView, aOrigOutputArea, bLokRTL] { - if (bLokRTL && aOrigOutputArea != pOtherEditView->GetOutputArea()) - pOtherEditView->SetOutputArea(aOrigOutputArea); - }); - - aEditRect = rDevice.PixelToLogic(aEditRect); - if (bIsTiledRendering) - pOtherEditView->SetOutputArea(aEditRect); - else - aEditRect.Intersection(pOtherEditView->GetOutputArea()); - pOtherEditView->Paint(aEditRect, &rDevice); + // keep into account the zoom factor + static const double twipFactor = 15 * 1.76388889; // 26.45833335 + Point aNewOrigin((aOriginAbsPx.getX() * twipFactor) / static_cast<double>(aDrawMode.GetScaleX()), + (aOriginAbsPx.getY() * twipFactor) / static_cast<double>(aDrawMode.GetScaleY())); - // EditView will do the cursor notifications correctly if we're in - // print-twips messaging mode. - if (bIsTiledRendering && !comphelper::LibreOfficeKit::isCompatFlagSet( - comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs)) - { - // Now we need to get relative cursor position within the editview. - // This is for sending the pixel-aligned twips position of the cursor to the specific views with - // the same given zoom level. - tools::Rectangle aCursorRect = pOtherEditView->GetEditCursor(); - Point aCursPos = OutputDevice::LogicToLogic(aCursorRect.TopLeft(), - MapMode(MapUnit::Map100thMM), MapMode(MapUnit::MapTwip)); - - const MapMode& rDevMM = rDevice.GetMapMode(); - MapMode aMM(MapUnit::MapTwip); - aMM.SetScaleX(rDevMM.GetScaleX()); - aMM.SetScaleY(rDevMM.GetScaleY()); - - aBGAbs.AdjustLeft(1); - aBGAbs.AdjustTop(1); - aCursorRect = GetOutDev()->PixelToLogic(aBGAbs, aMM); - aCursorRect.setWidth(0); - aCursorRect.Move(aCursPos.getX(), 0); - // Sends view cursor position to views of all matching zooms if needed (avoids duplicates). - InvalidateLOKViewCursor(aCursorRect, aMM.GetScaleX(), aMM.GetScaleY()); - } + MapMode aNewMM = rDevice.GetMapMode(); + aNewMM.SetOrigin(aNewOrigin); + rDevice.SetMapMode(aNewMM); - // Rollback the mapmode and 'output area'. - rOtherWin.SetMapMode(aOrigMapMode); - if (!bIsTiledRendering) - pOtherEditView->SetOutputArea(aOrigOutputArea); - rDevice.SetMapMode(MapMode(MapUnit::MapPixel)); - } - } + // paint the background + rDevice.DrawRect(rDevice.PixelToLogic(aBackground)); + + // paint text + const tools::Rectangle aOrigOutputAreaTw(pOtherEditView->GetOutputArea()); // Not in pixels. + + tools::Rectangle aNewOutputArea; + // compute output area for view with a different zoom level wrt the view used for painting + if (!(mrViewData.GetZoomX() == rOtherViewData.GetZoomX() && + mrViewData.GetZoomY() == rOtherViewData.GetZoomY())) + { + Point aOtherStart = rOtherViewData.GetScrPos( nCol1, nRow1, eOtherWhich ); + Point aOtherEnd = rOtherViewData.GetScrPos( nCol2+1, nRow2+1, eOtherWhich ); + tools::Rectangle aOtherEditRectPx(aOtherStart, aOtherEnd); + + tools::Long sides[4]; + for (auto i: {0, 1, 2, 3}) + { + sides[i] = static_cast<tools::Long>( + GetSide(aEditRectPx, i) + + double(::GetZoom(mrViewData, i) / ::GetZoom(rOtherViewData, i)) + * (double(::GetZoom(rOtherViewData, i)) * GetSide(aOrigOutputAreaTw, i) + - GetSide(aOtherEditRectPx, i) * twipFactor) + / twipFactor); + } + + aNewOutputArea = tools::Rectangle(sides[0], sides[1], sides[2], sides[3]); + aNewOutputArea += aOriginAbsPx; + } + // compute output area for RTL case + if (bLokRTL) + { + if (aNewOutputArea.IsEmpty()) + { + // same zoom level as view used for painting + aNewOutputArea = rDevice.LogicToPixel(aOrigOutputAreaTw); } + // Transform the cell range X coordinates such that the edit cell area is + // horizontally mirrored w.r.t the (combined-)tile. + aNewOutputArea = tools::Rectangle( + pLokRTLCtxt->docToTilePos(aNewOutputArea.Left() - aOriginAbsPx.X()) + aOriginAbsPx.X(), + aNewOutputArea.Top(), + pLokRTLCtxt->docToTilePos(aNewOutputArea.Right() - aOriginAbsPx.X()) + aOriginAbsPx.X(), + aNewOutputArea.Bottom()); + aNewOutputArea.Normalize(); } - pViewShell = SfxViewShell::GetNext(*pViewShell); - } + if (aNewOutputArea.IsEmpty()) + { + // same zoom level and not RTL: no need to change the output area before painting + pOtherEditView->Paint(rDevice.PixelToLogic(aTileRectPx), &rDevice); + } + else + { + // EditView has an 'output area' which is used to clip the 'paint area' we provide below. + // So they need to be in the same coordinates/units. This is tied to the mapmode of the gridwin + // attached to the EditView, so we have to change its mapmode too (temporarily). We save the + // original mapmode and 'output area' and roll them back when we finish painting to rDevice. + OutputDevice& rOtherWin = pOtherEditView->GetOutputDevice(); + const MapMode aOrigMapMode = rOtherWin.GetMapMode(); + rOtherWin.SetMapMode(rDevice.GetMapMode()); + + // Avoid sending wrong cursor/selection messages by the 'other' view, as the output-area is going + // to be tweaked temporarily to match the current view's zoom. + SuppressEditViewMessagesGuard aGuard(*pOtherEditView); + + pOtherEditView->SetOutputArea(rDevice.PixelToLogic(aNewOutputArea)); + pOtherEditView->Paint(rDevice.PixelToLogic(aTileRectPx), &rDevice); + + // EditView will do the cursor notifications correctly if we're in + // print-twips messaging mode. + if (pTabViewShell == pThisViewShell + && !comphelper::LibreOfficeKit::isCompatFlagSet( + comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs)) + { + // Now we need to get relative cursor position within the editview. + // This is for sending the pixel-aligned twips position of the cursor to the specific views with + // the same given zoom level. + tools::Rectangle aCursorRect = pEditView->GetEditCursor(); + Point aCursPos = o3tl::toTwips(aCursorRect.TopLeft(), o3tl::Length::mm100); + + const MapMode& rDevMM = rDevice.GetMapMode(); + MapMode aMM(MapUnit::MapTwip); + aMM.SetScaleX(rDevMM.GetScaleX()); + aMM.SetScaleY(rDevMM.GetScaleY()); + + aBGAbs.AdjustLeft(1); + aBGAbs.AdjustTop(1); + aCursorRect = GetOutDev()->PixelToLogic(aBGAbs, aMM); + aCursorRect.setWidth(0); + aCursorRect.Move(aCursPos.getX(), 0); + // Sends view cursor position to views of all matching zooms if needed (avoids duplicates). + InvalidateLOKViewCursor(aCursorRect, aMM.GetScaleX(), aMM.GetScaleY()); + } + // Rollback the mapmode and 'output area'. + rOtherWin.SetMapMode(aOrigMapMode); + pOtherEditView->SetOutputArea(aOrigOutputAreaTw); + } + rDevice.SetMapMode(MapMode(MapUnit::MapPixel)); + } } // In-place editing - when the user is typing, we need to paint the text // using the editeng. // It's being done after EndDrawLayers() to get it outside the overlay // buffer and on top of everything. - if (bInPlaceEditing) + if (bInPlaceEditing && !bIsTiledRendering) { // get the coordinates of the area we need to clear (overpaint by // the background) @@ -1284,14 +1279,6 @@ void ScGridWindow::DrawContent(OutputDevice &rDevice, const ScTableInfo& rTableI Point aStart = mrViewData.GetScrPos( nCol1, nRow1, eWhich ); Point aEnd = mrViewData.GetScrPos( nCol2+1, nRow2+1, eWhich ); - if (bLokRTL) - { - // Transform the cell range X coordinates such that the edit cell area is - // horizontally mirrored w.r.t the (combined-)tile. - aStart.setX(pLokRTLCtxt->docToTilePos(aStart.X())); - aEnd.setX(pLokRTLCtxt->docToTilePos(aEnd.X())); - } - // don't overwrite grid tools::Long nLayoutSign = bLayoutRTL ? -1 : 1; aEnd.AdjustX( -(2 * nLayoutSign) ); @@ -1299,96 +1286,20 @@ void ScGridWindow::DrawContent(OutputDevice &rDevice, const ScTableInfo& rTableI // set the correct mapmode tools::Rectangle aBackground(aStart, aEnd); - if (bLokRTL) - aBackground.Normalize(); - tools::Rectangle aBGAbs(aBackground); - if (bIsTiledRendering) - { - // Need to draw the background in absolute coords. - Point aOrigin = aOriginalMode.GetOrigin(); - aOrigin.setX(o3tl::convert(aOrigin.getX(), o3tl::Length::twip, o3tl::Length::px) - + nScrX); - aOrigin.setY(o3tl::convert(aOrigin.getY(), o3tl::Length::twip, o3tl::Length::px) - + nScrY); - aBackground += aOrigin; - rDevice.SetMapMode(aDrawMode); - } - else - rDevice.SetMapMode(mrViewData.GetLogicMode()); + // paint the background + rDevice.SetMapMode(mrViewData.GetLogicMode()); - if (bIsTiledRendering) - { - Point aOrigin = aOriginalMode.GetOrigin(); - aOrigin.setX(o3tl::convert(aOrigin.getX(), o3tl::Length::twip, o3tl::Length::px) - + nScrX); - aOrigin.setY(o3tl::convert(aOrigin.getY(), o3tl::Length::twip, o3tl::Length::px) - + nScrY); - static const double twipFactor = 15 * 1.76388889; // 26.45833335 - // keep into account the zoom factor - aOrigin = Point((aOrigin.getX() * twipFactor) / static_cast<double>(aDrawMode.GetScaleX()), - (aOrigin.getY() * twipFactor) / static_cast<double>(aDrawMode.GetScaleY())); - MapMode aNew = rDevice.GetMapMode(); - aNew.SetOrigin(aOrigin); - rDevice.SetMapMode(aNew); - } + tools::Rectangle aLogicRect(rDevice.PixelToLogic(aBackground)); + //tdf#100925, rhbz#1283420, Draw some text here, to get + //X11CairoTextRender::getCairoContext called, so that the forced read + //from the underlying X Drawable gets it to sync. + rDevice.DrawText(aLogicRect.BottomLeft(), " "); + rDevice.DrawRect(aLogicRect); // paint the editeng text - if (bIsTiledRendering) - { - // EditView has an 'output area' which is used to clip the paint area we provide below. - // So they need to be in the same coordinates/units. This is tied to the mapmode of the gridwin - // attached to the EditView, so we have to change its mapmode too (temporarily). We save the - // original mapmode and 'output area' and roll them back when we finish painting to rDevice. - const MapMode aOrigMapMode = GetMapMode(); - SetMapMode(rDevice.GetMapMode()); - - // Avoid sending wrong cursor/selection messages by the current view, as the output-area is going - // to be tweaked temporarily to match other view's zoom. (This does not affect the manual - // cursor-messaging done in the non print-twips mode) - SuppressEditViewMessagesGuard aGuard(*pEditView); - - // EditView will do the cursor notifications correctly if we're in - // print-twips messaging mode. - if (!comphelper::LibreOfficeKit::isCompatFlagSet( - comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs)) - { - // Now we need to get relative cursor position within the editview. - // This is for sending the pixel-aligned twips position of the cursor to the specific views with - // the same given zoom level. - tools::Rectangle aCursorRect = pEditView->GetEditCursor(); - Point aCursPos = o3tl::toTwips(aCursorRect.TopLeft(), o3tl::Length::mm100); - - const MapMode& rDevMM = rDevice.GetMapMode(); - MapMode aMM(MapUnit::MapTwip); - aMM.SetScaleX(rDevMM.GetScaleX()); - aMM.SetScaleY(rDevMM.GetScaleY()); - - aBGAbs.AdjustLeft(1); - aBGAbs.AdjustTop(1); - aCursorRect = GetOutDev()->PixelToLogic(aBGAbs, aMM); - aCursorRect.setWidth(0); - aCursorRect.Move(aCursPos.getX(), 0); - // Sends view cursor position to views of all matching zooms if needed (avoids duplicates). - InvalidateLOKViewCursor(aCursorRect, aMM.GetScaleX(), aMM.GetScaleY()); - } - - // Rollback the mapmode and 'output area'. - SetMapMode(aOrigMapMode); - } - else - { - // paint the background - tools::Rectangle aLogicRect(rDevice.PixelToLogic(aBackground)); - //tdf#100925, rhbz#1283420, Draw some text here, to get - //X11CairoTextRender::getCairoContext called, so that the forced read - //from the underlying X Drawable gets it to sync. - rDevice.DrawText(aLogicRect.BottomLeft(), " "); - rDevice.DrawRect(aLogicRect); - - tools::Rectangle aEditRect(Point(nScrX, nScrY), Size(aOutputData.GetScrW(), aOutputData.GetScrH())); - pEditView->Paint(rDevice.PixelToLogic(aEditRect), &rDevice); - } + tools::Rectangle aEditRect(Point(nScrX, nScrY), Size(aOutputData.GetScrW(), aOutputData.GetScrH())); + pEditView->Paint(rDevice.PixelToLogic(aEditRect), &rDevice); rDevice.SetMapMode(MapMode(MapUnit::MapPixel)); diff --git a/sc/source/ui/view/viewdata.cxx b/sc/source/ui/view/viewdata.cxx index 4ce7acd94391..964ceba34688 100644 --- a/sc/source/ui/view/viewdata.cxx +++ b/sc/source/ui/view/viewdata.cxx @@ -2248,6 +2248,7 @@ void ScViewData::EditGrowY( bool bInitial ) void ScViewData::ResetEditView() { + LOKEditViewHistory::Update(/*bRemove: */ true); EditEngine* pEngine = nullptr; for (sal_uInt16 i=0; i<4; i++) { @@ -2270,6 +2271,7 @@ void ScViewData::ResetEditView() void ScViewData::KillEditView() { + LOKEditViewHistory::Update(/*bRemove: */ true); for (sal_uInt16 i=0; i<4; i++) if (pEditView[i]) { diff --git a/sfx2/source/view/lokhelper.cxx b/sfx2/source/view/lokhelper.cxx index 2aa5792ebe1e..4a59ffbd3322 100644 --- a/sfx2/source/view/lokhelper.cxx +++ b/sfx2/source/view/lokhelper.cxx @@ -1133,4 +1133,82 @@ SfxLokLanguageGuard::~SfxLokLanguageGuard() comphelper::LibreOfficeKit::setLocale(m_pOldShell->GetLOKLocale()); } +LOKEditViewHistory::EditViewHistoryMap LOKEditViewHistory::maEditViewHistory; + + +void LOKEditViewHistory::Update(bool bRemove) +{ + if (!comphelper::LibreOfficeKit::isActive()) + return; + + static std::mutex aMutex; + SfxViewShell* pViewShell = SfxViewShell::Current(); + if (pViewShell) + { + std::lock_guard<std::mutex> aLockGuard{aMutex}; + int nDocId = pViewShell->GetDocId().get(); + if (maEditViewHistory.find(nDocId) != maEditViewHistory.end()) + maEditViewHistory[nDocId].remove(pViewShell); + if (!bRemove) + { + maEditViewHistory[nDocId].push_back(pViewShell); + if (maEditViewHistory[nDocId].size() > 10) + maEditViewHistory[nDocId].pop_front(); + } + } +} + +ViewShellList LOKEditViewHistory::GetHistoryForDoc(ViewShellDocId aDocId) +{ + int nDocId = aDocId.get(); + ViewShellList aResult; + if (maEditViewHistory.find(nDocId) != maEditViewHistory.end()) + aResult = maEditViewHistory.at(nDocId); + return aResult; +} + + ViewShellList LOKEditViewHistory::GetSortedViewsForDoc(ViewShellDocId aDocId) + { + ViewShellList aEditViewHistoryForDoc = LOKEditViewHistory::GetHistoryForDoc(aDocId); + // all views where document is loaded + ViewShellList aCurrentDocViewList; + // active views that are listed in the edit history + ViewShellList aEditedViewList; + + // Populate aCurrentDocViewList and aEditedViewList + SfxViewShell* pViewShell = SfxViewShell::GetFirst(); + while (pViewShell) + { + if (pViewShell->GetDocId() == aDocId) + { + if (aEditViewHistoryForDoc.empty() || + std::find(aEditViewHistoryForDoc.begin(), aEditViewHistoryForDoc.end(), + pViewShell) == aEditViewHistoryForDoc.end()) + { + // append views not listed in the edit history; + // the edit history is limited to 10 views, + // so it could miss some view where in place editing is occurring + aCurrentDocViewList.push_back(pViewShell); + } + else + { + // view is listed in the edit history + aEditedViewList.push_back(pViewShell); + } + } + pViewShell = SfxViewShell::GetNext(*pViewShell); + } + + // in case some no more active view needs to be removed from the history + aEditViewHistoryForDoc.remove_if( + [&aEditedViewList](SfxViewShell* pHistoryItem) { + return std::find(aEditedViewList.begin(), aEditedViewList.end(), pHistoryItem) == aEditedViewList.end(); + }); + + // place views belonging to the edit history at the end + aCurrentDocViewList.splice(aCurrentDocViewList.end(), aEditViewHistoryForDoc); + + return aCurrentDocViewList; + } + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |