editeng/source/editeng/impedit.hxx | 1 editeng/source/editeng/impedit2.cxx | 103 ++++++++++++++++-------------- include/svx/svxids.hrc | 7 +- sw/source/uibase/docvw/AnnotationWin2.cxx | 30 +++++--- sw/source/uibase/fldui/fldmgr.cxx | 9 ++ sw/source/uibase/inc/fldmgr.hxx | 1 sw/source/uibase/wrtsh/wrtsh1.cxx | 12 +++ 7 files changed, 102 insertions(+), 61 deletions(-)
New commits: commit a3a59876a48688d39e9057bad4d6c7ebb440ecea Author: Michael Stahl <[email protected]> AuthorDate: Fri Feb 14 14:11:10 2025 +0100 Commit: Michael Stahl <[email protected]> CommitDate: Fri Apr 4 13:06:48 2025 +0200 editeng: factor out ImpEditEngine::UpdateSelection() Change-Id: Ia6f694a813ad30aadf159db0f75fb1a86e9663dd Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181676 Reviewed-by: Michael Stahl <[email protected]> Tested-by: Jenkins diff --git a/editeng/source/editeng/impedit.hxx b/editeng/source/editeng/impedit.hxx index 76dea3933b68..fc7d376af6dd 100644 --- a/editeng/source/editeng/impedit.hxx +++ b/editeng/source/editeng/impedit.hxx @@ -1007,6 +1007,7 @@ public: const SfxItemSet& GetEmptyItemSet() const; + bool UpdateSelection(EditSelection &); void UpdateSelections(); void EnableUndo( bool bEnable ); diff --git a/editeng/source/editeng/impedit2.cxx b/editeng/source/editeng/impedit2.cxx index 2e61efacd028..bc00e49613d0 100644 --- a/editeng/source/editeng/impedit2.cxx +++ b/editeng/source/editeng/impedit2.cxx @@ -3740,6 +3740,60 @@ sal_uInt32 ImpEditEngine::GetParaHeight(sal_Int32 nParagraph) const return nHeight; } +bool ImpEditEngine::UpdateSelection(EditSelection & rCurSel) +{ + bool bChanged = false; + for (const std::unique_ptr<DeletedNodeInfo> & aDeletedNode : maDeletedNodes) + { + const DeletedNodeInfo& rInf = *aDeletedNode; + if ((rCurSel.Min().GetNode() == rInf.GetNode()) || + (rCurSel.Max().GetNode() == rInf.GetNode())) + { + // Use ParaPortions, as now also hidden paragraphs have to be + // taken into account! + sal_Int32 nPara = rInf.GetPosition(); + if (!GetParaPortions().exists(nPara)) // Last paragraph + { + nPara = GetParaPortions().lastIndex(); + } + assert(GetParaPortions().exists(nPara) && "Empty Document in UpdateSelections ?"); + // Do not end up from a hidden paragraph: + sal_Int32 nCurrentPara = nPara; + sal_Int32 nLastParaIndex = GetParaPortions().lastIndex(); + while (nPara <= nLastParaIndex && !GetParaPortions().getRef(nPara).IsVisible()) + nPara++; + if (nPara > nLastParaIndex) // then also backwards ... + { + nPara = nCurrentPara; + while ( nPara && !GetParaPortions().getRef(nPara).IsVisible() ) + nPara--; + } + OSL_ENSURE(GetParaPortions().getRef(nPara).IsVisible(), "No visible paragraph found: UpdateSelections" ); + + ParaPortion& rParaPortion = GetParaPortions().getRef(nPara); + EditSelection aTmpSelection(EditPaM(rParaPortion.GetNode(), 0)); + rCurSel = aTmpSelection; + bChanged=true; + break; // for loop + } + } + if ( !bChanged ) + { + // Check Index if node shrunk. + if (rCurSel.Min().GetIndex() > rCurSel.Min().GetNode()->Len()) + { + rCurSel.Min().SetIndex(rCurSel.Min().GetNode()->Len()); + bChanged = true; + } + if (rCurSel.Max().GetIndex() > rCurSel.Max().GetNode()->Len()) + { + rCurSel.Max().SetIndex(rCurSel.Max().GetNode()->Len()); + bChanged = true; + } + } + return bChanged; +} + void ImpEditEngine::UpdateSelections() { // Check whether one of the selections is at a deleted node... @@ -3747,54 +3801,9 @@ void ImpEditEngine::UpdateSelections() for (EditView* pView : maEditViews) { EditSelection aCurSel( pView->getImpl().GetEditSelection() ); - bool bChanged = false; - for (const std::unique_ptr<DeletedNodeInfo> & aDeletedNode : maDeletedNodes) + if (UpdateSelection(aCurSel)) { - const DeletedNodeInfo& rInf = *aDeletedNode; - if ( ( aCurSel.Min().GetNode() == rInf.GetNode() ) || - ( aCurSel.Max().GetNode() == rInf.GetNode() ) ) - { - // Use ParaPortions, as now also hidden paragraphs have to be - // taken into account! - sal_Int32 nPara = rInf.GetPosition(); - if (!GetParaPortions().exists(nPara)) // Last paragraph - { - nPara = GetParaPortions().lastIndex(); - } - assert(GetParaPortions().exists(nPara) && "Empty Document in UpdateSelections ?"); - // Do not end up from a hidden paragraph: - sal_Int32 nCurrentPara = nPara; - sal_Int32 nLastParaIndex = GetParaPortions().lastIndex(); - while (nPara <= nLastParaIndex && !GetParaPortions().getRef(nPara).IsVisible()) - nPara++; - if (nPara > nLastParaIndex) // then also backwards ... - { - nPara = nCurrentPara; - while ( nPara && !GetParaPortions().getRef(nPara).IsVisible() ) - nPara--; - } - OSL_ENSURE(GetParaPortions().getRef(nPara).IsVisible(), "No visible paragraph found: UpdateSelections" ); - - ParaPortion& rParaPortion = GetParaPortions().getRef(nPara); - EditSelection aTmpSelection(EditPaM(rParaPortion.GetNode(), 0)); - pView->getImpl().SetEditSelection( aTmpSelection ); - bChanged=true; - break; // for loop - } - } - if ( !bChanged ) - { - // Check Index if node shrunk. - if ( aCurSel.Min().GetIndex() > aCurSel.Min().GetNode()->Len() ) - { - aCurSel.Min().SetIndex( aCurSel.Min().GetNode()->Len() ); - pView->getImpl().SetEditSelection( aCurSel ); - } - if ( aCurSel.Max().GetIndex() > aCurSel.Max().GetNode()->Len() ) - { - aCurSel.Max().SetIndex( aCurSel.Max().GetNode()->Len() ); - pView->getImpl().SetEditSelection( aCurSel ); - } + pView->getImpl().SetEditSelection(aCurSel); } } maDeletedNodes.clear(); commit 46000e9db470c6d7735aac050dd5e944c79d9b38 Author: Michael Stahl <[email protected]> AuthorDate: Thu Apr 3 17:49:13 2025 +0200 Commit: Michael Stahl <[email protected]> CommitDate: Fri Apr 4 13:06:38 2025 +0200 svx,sw: when replying to comment, set parent ids immediately ... and not after insertion is already finished. This requires 3 new slots because SwWrtShell::InsertPostIt() takes a SfxRequest... Then SwInsertField_Data needs another different temporary representation. Open question is why does a comment need to have 3 different ids. Change-Id: Ie655c4f089240b8407c52288b2f96653299665c8 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/183686 Tested-by: Jenkins Reviewed-by: Michael Stahl <[email protected]> diff --git a/include/svx/svxids.hrc b/include/svx/svxids.hrc index 8b18de6306e8..4885e058c01a 100644 --- a/include/svx/svxids.hrc +++ b/include/svx/svxids.hrc @@ -1076,9 +1076,12 @@ class XFillGradientItem; #define SID_PROTECTSIZE TypedWhichId<SfxBoolItem>( SID_SVX_START + 1216 ) #define SID_PROTECTPOS TypedWhichId<SfxBoolItem>( SID_SVX_START + 1217 ) -// IMPORTANT NOTE: adjust SID_SVX_FIRSTFREE, when adding new slot id -#define SID_SVX_FIRSTFREE ( SID_SVX_START + 1217 + 1 ) +#define SID_ATTR_POSTIT_PARENTPARAID TypedWhichId<SvxPostItIdItem>(SID_SVX_START + 1218) +#define SID_ATTR_POSTIT_PARENTPOSTITID TypedWhichId<SvxPostItIdItem>(SID_SVX_START + 1219) +#define SID_ATTR_POSTIT_PARENTNAME TypedWhichId<SfxStringItem>(SID_SVX_START + 1220) +// IMPORTANT NOTE: adjust SID_SVX_FIRSTFREE, when adding new slot id +#define SID_SVX_FIRSTFREE (SID_SVX_START + 1220 + 1) // Overflow check for slot IDs #if SID_SVX_FIRSTFREE > SID_SVX_END diff --git a/sw/source/uibase/docvw/AnnotationWin2.cxx b/sw/source/uibase/docvw/AnnotationWin2.cxx index 6bd5eeb72992..6b495bc6ec03 100644 --- a/sw/source/uibase/docvw/AnnotationWin2.cxx +++ b/sw/source/uibase/docvw/AnnotationWin2.cxx @@ -64,6 +64,8 @@ #include <vcl/uitest/logger.hxx> #include <vcl/uitest/eventdescription.hxx> +#include <svx/postattr.hxx> + #include <edtwin.hxx> #include <view.hxx> #include <docsh.hxx> @@ -1068,20 +1070,26 @@ void SwAnnotationWin::ExecuteCommand(sal_uInt16 nSlot) SwitchToFieldPos(); SwDocShell* pShell = mrView.GetDocShell(); - if (bReply) + if (!bReply) + { + // synchronous dispatch + mrView.GetViewFrame().GetDispatcher()->Execute(FN_POSTIT); + } + else + { pShell->GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT, nullptr); + SvxPostItIdItem parentParaId{SID_ATTR_POSTIT_PARENTPARAID}; + parentParaId.SetValue(OUString::number(GetParaId())); + SvxPostItIdItem parentPostitId{SID_ATTR_POSTIT_PARENTPOSTITID}; + parentPostitId.SetValue(OUString::number(GetPostItField()->GetPostItId())); + this->GeneratePostItName(); + SfxStringItem const parentName{SID_ATTR_POSTIT_PARENTNAME, + GetPostItField()->GetName()}; + // transport parent ids to SwWrtShell::InsertPostIt() + SfxPoolItem const* items[]{ &parentParaId, &parentPostitId, &parentName, nullptr }; + mrView.GetViewFrame().GetDispatcher()->Execute(FN_POSTIT, SfxCallMode::SLOT, items); - // synchronous dispatch - mrView.GetViewFrame().GetDispatcher()->Execute(FN_POSTIT); - - if (bReply) - { - // Get newly created SwPostItField and set its paraIdParent auto pPostItField = mrMgr.GetLatestPostItField(); - pPostItField->SetParentId(GetParaId()); - pPostItField->SetParentPostItId(GetPostItField()->GetPostItId()); - this->GeneratePostItName(); - pPostItField->SetParentName(GetPostItField()->GetName()); // In this case, force generating the associated window // synchronously so we can bundle its use of the registered diff --git a/sw/source/uibase/fldui/fldmgr.cxx b/sw/source/uibase/fldui/fldmgr.cxx index cfef4e3e7bf5..cd738a47f710 100644 --- a/sw/source/uibase/fldui/fldmgr.cxx +++ b/sw/source/uibase/fldui/fldmgr.cxx @@ -902,7 +902,7 @@ bool SwFieldMgr::InsertField( { SvtUserOptions aUserOpt; SwPostItFieldType* pType = static_cast<SwPostItFieldType*>(pCurShell->GetFieldType(0, SwFieldIds::Postit)); - pField.reset( + auto const pPostItField( new SwPostItField( pType, rData.m_sPar1, // author @@ -910,6 +910,13 @@ bool SwFieldMgr::InsertField( aUserOpt.GetID(), // author's initials OUString(), // name DateTime(DateTime::SYSTEM) )); + if (rData.m_oParentId) + { + pPostItField->SetParentId(std::get<0>(*rData.m_oParentId)); + pPostItField->SetParentPostItId(std::get<1>(*rData.m_oParentId)); + pPostItField->SetParentName(std::get<2>(*rData.m_oParentId)); + } + pField.reset(pPostItField); } break; case SwFieldTypesEnum::Script: diff --git a/sw/source/uibase/inc/fldmgr.hxx b/sw/source/uibase/inc/fldmgr.hxx index 48d4500513c4..8f3409aa0694 100644 --- a/sw/source/uibase/inc/fldmgr.hxx +++ b/sw/source/uibase/inc/fldmgr.hxx @@ -83,6 +83,7 @@ struct SwInsertField_Data weld::Widget* m_pParent; // parent widget used for SwWrtShell::StartInputFieldDlg() /// Marks the PostIt field's annotation start/end if it differs from the cursor selection. std::optional<SwPaM> m_oAnnotationRange; + std::optional<std::tuple<sal_uInt32, sal_uInt32, OUString>> m_oParentId; SwInsertField_Data(SwFieldTypesEnum nType, sal_uInt16 nSub, OUString aPar1, OUString aPar2, sal_uInt32 nFormatId, SwWrtShell* pShell = nullptr, sal_Unicode cSep = ' ', bool bIsAutoLanguage = true) : diff --git a/sw/source/uibase/wrtsh/wrtsh1.cxx b/sw/source/uibase/wrtsh/wrtsh1.cxx index 80d263fb4e69..0444700deff1 100644 --- a/sw/source/uibase/wrtsh/wrtsh1.cxx +++ b/sw/source/uibase/wrtsh/wrtsh1.cxx @@ -2325,6 +2325,18 @@ void SwWrtShell::InsertPostIt(SwFieldMgr& rFieldMgr, const SfxRequest& rReq) SwInsertField_Data aData(SwFieldTypesEnum::Postit, 0, sAuthor, sText, 0); + { + SvxPostItIdItem const*const pParentParaIdItem{rReq.GetArg<SvxPostItIdItem>(SID_ATTR_POSTIT_PARENTPARAID)}; + SvxPostItIdItem const*const pParentPostItIdItem{rReq.GetArg<SvxPostItIdItem>(SID_ATTR_POSTIT_PARENTPOSTITID)}; + SfxStringItem const*const pParentNameItem{rReq.GetArg<SfxStringItem>(SID_ATTR_POSTIT_PARENTNAME)}; + if (pParentParaIdItem && pParentPostItIdItem && pParentNameItem) + { + aData.m_oParentId.emplace(pParentParaIdItem->GetValue().toUInt32(), + pParentPostItIdItem->GetValue().toUInt32(), + pParentNameItem->GetValue()); + } + } + if (IsSelFrameMode()) { SwFlyFrame* pFly = GetSelectedFlyFrame();
