sw/inc/IDocumentMarkAccess.hxx | 4 ++-- sw/inc/crsrsh.hxx | 4 ++-- sw/qa/extras/uiwriter/uiwriter4.cxx | 2 +- sw/source/core/crsr/crbm.cxx | 8 ++++---- sw/source/core/doc/docbm.cxx | 27 ++++++++++++++++++++------- sw/source/core/inc/MarkManager.hxx | 4 ++-- sw/source/ui/vba/vbaformfield.cxx | 10 ++++++---- sw/source/uibase/docvw/edtwin.cxx | 6 ++++-- sw/source/uibase/wrtsh/wrtsh1.cxx | 4 ++-- 9 files changed, 43 insertions(+), 26 deletions(-)
New commits: commit e125e6623fa1c0f39d927bb37547ca6d1e299cb1 Author: Justin Luth <justin.l...@collabora.com> AuthorDate: Mon Jan 23 11:18:44 2023 -0500 Commit: Justin Luth <jl...@mail.com> CommitDate: Tue Jan 24 22:22:11 2023 +0000 related tdf#151548 formfield navigation: loop to beginning/end When reaching the end of the form using keyboard navigation, the next tabstop should return the user to the beginning of the form. This patch adds that to the existing legacy formfield navigation. I'll wait with a unit test until I have added activeX/contentControls into the mix. Change-Id: I24a15a60f5a0a2721f512cca50397efddcbf7e4b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/146035 Tested-by: Jenkins Reviewed-by: Justin Luth <jl...@mail.com> diff --git a/sw/inc/IDocumentMarkAccess.hxx b/sw/inc/IDocumentMarkAccess.hxx index 391be58a077a..b1317993dfb7 100644 --- a/sw/inc/IDocumentMarkAccess.hxx +++ b/sw/inc/IDocumentMarkAccess.hxx @@ -328,8 +328,8 @@ class IDocumentMarkAccess /// get Fieldmark for CH_TXT_ATR_FIELDSTART/CH_TXT_ATR_FIELDEND at rPos virtual ::sw::mark::IFieldmark* getFieldmarkAt(const SwPosition& rPos) const =0; virtual ::sw::mark::IFieldmark* getFieldmarkFor(const SwPosition& pos) const =0; - virtual ::sw::mark::IFieldmark* getFieldmarkBefore(const SwPosition& pos) const =0; - virtual ::sw::mark::IFieldmark* getFieldmarkAfter(const SwPosition& pos) const =0; + virtual sw::mark::IFieldmark* getFieldmarkBefore(const SwPosition& pos, bool bLoop) const =0; + virtual sw::mark::IFieldmark* getFieldmarkAfter(const SwPosition& pos, bool bLoop) const =0; virtual ::sw::mark::IFieldmark* getDropDownFor(const SwPosition& pos) const=0; virtual std::vector<::sw::mark::IFieldmark*> getNoTextFieldmarksIn(const SwPaM &rPaM) const=0; diff --git a/sw/inc/crsrsh.hxx b/sw/inc/crsrsh.hxx index 2e9a9f0f1e62..31cad2cd6e71 100644 --- a/sw/inc/crsrsh.hxx +++ b/sw/inc/crsrsh.hxx @@ -579,8 +579,8 @@ public: bool IsFormProtected(); ::sw::mark::IFieldmark* GetCurrentFieldmark(); - ::sw::mark::IFieldmark* GetFieldmarkAfter(); - ::sw::mark::IFieldmark* GetFieldmarkBefore(); + sw::mark::IFieldmark* GetFieldmarkAfter(bool bLoop); + sw::mark::IFieldmark* GetFieldmarkBefore(bool bLoop); bool GotoFieldmark( const ::sw::mark::IFieldmark* const pMark ); // update Cursr, i.e. reset it into content should only be called when the diff --git a/sw/qa/extras/uiwriter/uiwriter4.cxx b/sw/qa/extras/uiwriter/uiwriter4.cxx index 77b42667ee87..b7f05b3960e6 100644 --- a/sw/qa/extras/uiwriter/uiwriter4.cxx +++ b/sw/qa/extras/uiwriter/uiwriter4.cxx @@ -1486,7 +1486,7 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, testTdf95699) pMarkAccess = aClipboard.getIDocumentMarkAccess(); CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount()); ::sw::mark::IFieldmark* pFieldMark - = pMarkAccess->getFieldmarkAfter(SwPosition(pDoc->GetNodes().GetEndOfExtras())); + = pMarkAccess->getFieldmarkAfter(SwPosition(pDoc->GetNodes().GetEndOfExtras()), false); CPPUNIT_ASSERT_EQUAL(OUString("vnd.oasis.opendocument.field.FORMCHECKBOX"), pFieldMark->GetFieldname()); } diff --git a/sw/source/core/crsr/crbm.cxx b/sw/source/core/crsr/crbm.cxx index 4e0b808c7fba..53d2538538d8 100644 --- a/sw/source/core/crsr/crbm.cxx +++ b/sw/source/core/crsr/crbm.cxx @@ -290,16 +290,16 @@ bool SwCursorShell::IsFormProtected() return getIDocumentMarkAccess()->getFieldmarkFor(pos); } -::sw::mark::IFieldmark* SwCursorShell::GetFieldmarkAfter() +sw::mark::IFieldmark* SwCursorShell::GetFieldmarkAfter(bool bLoop) { SwPosition pos(*GetCursor()->GetPoint()); - return getIDocumentMarkAccess()->getFieldmarkAfter(pos); + return getIDocumentMarkAccess()->getFieldmarkAfter(pos, bLoop); } -::sw::mark::IFieldmark* SwCursorShell::GetFieldmarkBefore() +sw::mark::IFieldmark* SwCursorShell::GetFieldmarkBefore(bool bLoop) { SwPosition pos(*GetCursor()->GetPoint()); - return getIDocumentMarkAccess()->getFieldmarkBefore(pos); + return getIDocumentMarkAccess()->getFieldmarkBefore(pos, bLoop); } bool SwCursorShell::GotoFieldmark(::sw::mark::IFieldmark const * const pMark) diff --git a/sw/source/core/doc/docbm.cxx b/sw/source/core/doc/docbm.cxx index 56a34fb72a3a..cd6afc472350 100644 --- a/sw/source/core/doc/docbm.cxx +++ b/sw/source/core/doc/docbm.cxx @@ -312,7 +312,8 @@ namespace }; - IMark* lcl_getMarkAfter(const MarkManager::container_t& rMarks, const SwPosition& rPos) + IMark* lcl_getMarkAfter(const MarkManager::container_t& rMarks, const SwPosition& rPos, + bool bLoop) { auto const pMarkAfter = upper_bound( rMarks.begin(), @@ -320,11 +321,17 @@ namespace rPos, CompareIMarkStartsAfter()); if(pMarkAfter == rMarks.end()) + { + if (bLoop && rMarks.begin() != rMarks.end()) + return *rMarks.begin(); + return nullptr; + } return *pMarkAfter; }; - IMark* lcl_getMarkBefore(const MarkManager::container_t& rMarks, const SwPosition& rPos) + IMark* lcl_getMarkBefore(const MarkManager::container_t& rMarks, const SwPosition& rPos, + bool bLoop) { // candidates from which to choose the mark before MarkManager::container_t vCandidates; @@ -342,7 +349,13 @@ namespace back_inserter(vCandidates), [&rPos] (const ::sw::mark::MarkBase *const pMark) { return !(pMark->GetMarkEnd() < rPos); } ); // no candidate left => we are in front of the first mark or there are none - if(vCandidates.empty()) return nullptr; + if(vCandidates.empty()) + { + if (bLoop && rMarks.begin() != rMarks.end()) + return *(rMarks.end() - 1); + + return nullptr; + } // return the highest (last) candidate using mark end ordering return *max_element(vCandidates.begin(), vCandidates.end(), &lcl_MarkOrderingByEnd); } @@ -1640,11 +1653,11 @@ namespace sw::mark return aRet; } - IFieldmark* MarkManager::getFieldmarkAfter(const SwPosition& rPos) const - { return dynamic_cast<IFieldmark*>(lcl_getMarkAfter(m_vFieldmarks, rPos)); } + IFieldmark* MarkManager::getFieldmarkAfter(const SwPosition& rPos, bool bLoop) const + { return dynamic_cast<IFieldmark*>(lcl_getMarkAfter(m_vFieldmarks, rPos, bLoop)); } - IFieldmark* MarkManager::getFieldmarkBefore(const SwPosition& rPos) const - { return dynamic_cast<IFieldmark*>(lcl_getMarkBefore(m_vFieldmarks, rPos)); } + IFieldmark* MarkManager::getFieldmarkBefore(const SwPosition& rPos, bool bLoop) const + { return dynamic_cast<IFieldmark*>(lcl_getMarkBefore(m_vFieldmarks, rPos, bLoop)); } IDocumentMarkAccess::const_iterator_t MarkManager::getAnnotationMarksBegin() const { diff --git a/sw/source/core/inc/MarkManager.hxx b/sw/source/core/inc/MarkManager.hxx index 7f9945043c72..6b6010ae5eb0 100644 --- a/sw/source/core/inc/MarkManager.hxx +++ b/sw/source/core/inc/MarkManager.hxx @@ -95,8 +95,8 @@ namespace sw::mark { virtual const_iterator_t getFieldmarksEnd() const override; virtual ::sw::mark::IFieldmark* getFieldmarkAt(const SwPosition& rPos) const override; virtual ::sw::mark::IFieldmark* getFieldmarkFor(const SwPosition& rPos) const override; - virtual ::sw::mark::IFieldmark* getFieldmarkBefore(const SwPosition& rPos) const override; - virtual ::sw::mark::IFieldmark* getFieldmarkAfter(const SwPosition& rPos) const override; + virtual sw::mark::IFieldmark* getFieldmarkBefore(const SwPosition& rPos, bool bLoop) const override; + virtual sw::mark::IFieldmark* getFieldmarkAfter(const SwPosition& rPos, bool bLoop) const override; virtual ::sw::mark::IFieldmark* getDropDownFor(const SwPosition &rPos) const override; virtual std::vector<::sw::mark::IFieldmark*> getNoTextFieldmarksIn(const SwPaM &rPaM) const override; diff --git a/sw/source/ui/vba/vbaformfield.cxx b/sw/source/ui/vba/vbaformfield.cxx index 8755e5620a7f..4669fdc5d4bd 100644 --- a/sw/source/ui/vba/vbaformfield.cxx +++ b/sw/source/ui/vba/vbaformfield.cxx @@ -71,13 +71,14 @@ uno::Any SwVbaFormField::Previous() if (!pMarkAccess) return uno::Any(); - sw::mark::IFieldmark* pFieldMark = pMarkAccess->getFieldmarkBefore(m_rFormField.GetMarkPos()); + sw::mark::IFieldmark* pFieldMark = pMarkAccess->getFieldmarkBefore(m_rFormField.GetMarkPos(), + /*bLoop=*/false); // DateFields are a LO specialty, and do not exist natively in MS documents. Ignore if added... auto pDateField = dynamic_cast<sw::mark::IDateFieldmark*>(pFieldMark); while (pDateField) { - pFieldMark = pMarkAccess->getFieldmarkBefore(pDateField->GetMarkPos()); + pFieldMark = pMarkAccess->getFieldmarkBefore(pDateField->GetMarkPos(), /*bLoop=*/false); pDateField = dynamic_cast<sw::mark::IDateFieldmark*>(pFieldMark); } @@ -98,13 +99,14 @@ uno::Any SwVbaFormField::Next() if (!pMarkAccess) return uno::Any(); - sw::mark::IFieldmark* pFieldMark = pMarkAccess->getFieldmarkAfter(m_rFormField.GetMarkPos()); + sw::mark::IFieldmark* pFieldMark = pMarkAccess->getFieldmarkAfter(m_rFormField.GetMarkPos(), + /*bLoop=*/false); // DateFields are a LO specialty, and do not exist natively in MS documents. Ignore if added... auto pDateField = dynamic_cast<sw::mark::IDateFieldmark*>(pFieldMark); while (pDateField) { - pFieldMark = pMarkAccess->getFieldmarkAfter(pDateField->GetMarkPos()); + pFieldMark = pMarkAccess->getFieldmarkAfter(pDateField->GetMarkPos(), /*bLoop=*/false); pDateField = dynamic_cast<sw::mark::IDateFieldmark*>(pFieldMark); } diff --git a/sw/source/uibase/docvw/edtwin.cxx b/sw/source/uibase/docvw/edtwin.cxx index b0a320168924..514d0d87d02c 100644 --- a/sw/source/uibase/docvw/edtwin.cxx +++ b/sw/source/uibase/docvw/edtwin.cxx @@ -2630,14 +2630,16 @@ KEYINPUT_CHECKTABLE_INSDEL: case SwKeyState::GotoNextFieldMark: { - ::sw::mark::IFieldmark const * const pFieldmark = rSh.GetFieldmarkAfter(); + const sw::mark::IFieldmark* pFieldmark + = rSh.GetFieldmarkAfter(/*bLoop=*/true); if(pFieldmark) rSh.GotoFieldmark(pFieldmark); } break; case SwKeyState::GotoPrevFieldMark: { - ::sw::mark::IFieldmark const * const pFieldmark = rSh.GetFieldmarkBefore(); + const sw::mark::IFieldmark* pFieldmark + = rSh.GetFieldmarkBefore(/*bLoop=*/true); if( pFieldmark ) rSh.GotoFieldmark(pFieldmark); } diff --git a/sw/source/uibase/wrtsh/wrtsh1.cxx b/sw/source/uibase/wrtsh/wrtsh1.cxx index b989343266cb..ab5882a1147b 100644 --- a/sw/source/uibase/wrtsh/wrtsh1.cxx +++ b/sw/source/uibase/wrtsh/wrtsh1.cxx @@ -2002,7 +2002,7 @@ SwWrtShell::SwWrtShell( SwWrtShell& rSh, vcl::Window *_pWin, SwView &rShell ) // place the cursor on the first field... IFieldmark *pBM = nullptr; - if ( IsFormProtected() && ( pBM = GetFieldmarkAfter( ) ) !=nullptr ) { + if (IsFormProtected() && (pBM = GetFieldmarkAfter(/*bLoop=*/false)) !=nullptr) { GotoFieldmark(pBM); } } @@ -2020,7 +2020,7 @@ SwWrtShell::SwWrtShell( SwDoc& rDoc, vcl::Window *_pWin, SwView &rShell, // place the cursor on the first field... IFieldmark *pBM = nullptr; - if ( IsFormProtected() && ( pBM = GetFieldmarkAfter( ) ) !=nullptr ) { + if (IsFormProtected() && (pBM = GetFieldmarkAfter(/*bLoop=*/false)) !=nullptr) { GotoFieldmark(pBM); } }