sw/inc/formatcontentcontrol.hxx | 2 + sw/inc/textcontentcontrol.hxx | 2 - sw/source/core/crsr/crstrvl.cxx | 3 -- sw/source/core/txtnode/attrcontentcontrol.cxx | 22 ++++----------------- sw/source/ui/vba/vbacontentcontrol.cxx | 5 ++-- sw/source/ui/vba/vbacontentcontrollistentry.cxx | 16 +++++++++++++-- sw/source/uibase/inc/wrtsh.hxx | 7 +++++- sw/source/uibase/wrtsh/wrtsh3.cxx | 25 +++++++++++++----------- 8 files changed, 45 insertions(+), 37 deletions(-)
New commits: commit 79553e784c6d4587814bc2a577d7251c458df8d4 Author: Justin Luth <justin.l...@collabora.com> AuthorDate: Mon Nov 28 11:20:06 2022 -0500 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Wed Nov 30 08:35:50 2022 +0100 tdf#151548 ContentControls: improve Invalidation This addresses some hack concerns that Miklos raised in his review. Change-Id: Ic6d906e9eb1d23700fb743e179ba87899ce2f4a1 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143412 Tested-by: Jenkins Reviewed-by: Justin Luth <jl...@mail.com> Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/sw/inc/formatcontentcontrol.hxx b/sw/inc/formatcontentcontrol.hxx index 415132409e10..88d32e83d31a 100644 --- a/sw/inc/formatcontentcontrol.hxx +++ b/sw/inc/formatcontentcontrol.hxx @@ -180,9 +180,11 @@ class SW_DLLPUBLIC SwContentControl : public sw::BroadcastingModify sal_Int32 m_nId = 0; /// Stores a list item index, in case the doc model is not yet updated. + // i.e. temporarily store the selected item until the text is inserted by GotoContentControl. std::optional<size_t> m_oSelectedListItem; /// Stores a date timestamp, in case the doc model is not yet updated. + // i.e. temporarily store the date until the text is inserted by GotoContentControl. std::optional<double> m_oSelectedDate; /** diff --git a/sw/inc/textcontentcontrol.hxx b/sw/inc/textcontentcontrol.hxx index 156b44804195..8c8a3b3ee044 100644 --- a/sw/inc/textcontentcontrol.hxx +++ b/sw/inc/textcontentcontrol.hxx @@ -42,7 +42,7 @@ public: void ChgTextNode(SwTextNode* pNode); SwTextNode* GetTextNode() const; - void Invalidate(bool bKeepPlaceholderStatus = true); + void Invalidate(); void dumpAsXml(xmlTextWriterPtr pWriter) const override; }; diff --git a/sw/source/core/crsr/crstrvl.cxx b/sw/source/core/crsr/crstrvl.cxx index 4b07f24a2234..db0ec5b1ae1f 100644 --- a/sw/source/core/crsr/crstrvl.cxx +++ b/sw/source/core/crsr/crstrvl.cxx @@ -854,9 +854,6 @@ bool SwCursorShell::GotoFormatContentControl(const SwFormatContentControl& rCont sal_Int32 nEnd = *pTextContentControl->End() - 1; pCursor->GetMark()->Assign(*pTextNode, nEnd); - // Assume that once the placeholder is selected, the content is no longer the placeholder. - pContentControl->SetShowingPlaceHolder(false); - bool bRet = !pCursor->IsSelOvr(); if (bRet) { diff --git a/sw/source/core/txtnode/attrcontentcontrol.cxx b/sw/source/core/txtnode/attrcontentcontrol.cxx index b4e060e75ffc..98cfa13f9611 100644 --- a/sw/source/core/txtnode/attrcontentcontrol.cxx +++ b/sw/source/core/txtnode/attrcontentcontrol.cxx @@ -662,33 +662,21 @@ SwTextNode* SwTextContentControl::GetTextNode() const return rFormatContentControl.GetTextNode(); } -void SwTextContentControl::Invalidate(bool bKeepPlaceholderStatus) +void SwTextContentControl::Invalidate() { SwDocShell* pDocShell = GetTextNode() ? GetTextNode()->GetDoc().GetDocShell() : nullptr; if (!pDocShell || !pDocShell->GetWrtShell()) return; // save the cursor + // NOTE: needs further testing to see if this is adequate (i.e. in auto-run macros...) pDocShell->GetWrtShell()->Push(); // visit the control in the text (which makes any necessary visual changes) - // NOTE: simply going to a control indicates cancelling m_bShowingPlaceHolder + // NOTE: simply going to a control indicates cancelling ShowingPlaceHolder, unless bOnlyRefresh + // NOTE: simply going to a checkbox causes a toggle, unless bOnlyRefresh auto& rFormatContentControl = static_cast<SwFormatContentControl&>(GetAttr()); - std::shared_ptr<SwContentControl> pCC = rFormatContentControl.GetContentControl(); - bKeepPlaceholderStatus = bKeepPlaceholderStatus && pCC && pCC->GetShowingPlaceHolder(); - - // NOTE: simply going to a checkbox causes a toggle - const bool bSaveChecked = pCC && pCC->GetChecked(); - if (pCC && pCC->GetCheckbox()) - pCC->SetChecked(!bSaveChecked); //do a double-toggle to keep the same value! - - pDocShell->GetWrtShell()->GotoContentControl(rFormatContentControl); - - assert((!pCC || !pCC->GetCheckbox() || bSaveChecked == pCC->GetChecked()) - && "invalidation implementation changed"); - - if (bKeepPlaceholderStatus) - pCC->SetShowingPlaceHolder(true); + pDocShell->GetWrtShell()->GotoContentControl(rFormatContentControl, /*bOnlyRefresh=*/true); pDocShell->GetWrtShell()->Pop(SwCursorShell::PopMode::DeleteCurrent); } diff --git a/sw/source/ui/vba/vbacontentcontrol.cxx b/sw/source/ui/vba/vbacontentcontrol.cxx index 66d104c567e6..d75ce84d7f4a 100644 --- a/sw/source/ui/vba/vbacontentcontrol.cxx +++ b/sw/source/ui/vba/vbacontentcontrol.cxx @@ -99,7 +99,8 @@ void SwVbaContentControl::setChecked(sal_Bool bSet) if (pCC->GetCheckbox() && pCC->GetChecked() != static_cast<bool>(bSet)) { pCC->SetChecked(bSet); - m_rCC.Invalidate(/*bKeepPlaceholderStatus=*/false); + pCC->SetShowingPlaceHolder(false); + m_rCC.Invalidate(); } } @@ -734,7 +735,7 @@ void SwVbaContentControl::SetPlaceholderText(const uno::Any& BuildingBlock, cons // Remove placeholder text. pCC->SetPlaceholderDocPart(""); } - m_rCC.Invalidate(/*bKeepPlaceholderStatus=true*/); + m_rCC.Invalidate(); } void SwVbaContentControl::Ungroup() { SAL_INFO("sw.vba", "SwVbaContentControl::UnGroup stub"); } diff --git a/sw/source/ui/vba/vbacontentcontrollistentry.cxx b/sw/source/ui/vba/vbacontentcontrollistentry.cxx index e666bbf0bcd7..61d2a1faf6a8 100644 --- a/sw/source/ui/vba/vbacontentcontrollistentry.cxx +++ b/sw/source/ui/vba/vbacontentcontrollistentry.cxx @@ -62,9 +62,20 @@ void SwVbaContentControlListEntry::setText(const OUString& rSet) if (vListItems[i].ToString() == rSet) return; } + + bool bNeedsInvalidation = false; + if (!pCC->GetShowingPlaceHolder()) + { + // TODO: implement bCheckDocModel + std::optional<size_t> oSel(pCC->GetSelectedListItem(/*bCheckDocModel=true*/)); + bNeedsInvalidation = oSel && *oSel == m_nZIndex; + } + vListItems[m_nZIndex].m_aDisplayText = rSet; pCC->SetListItems(vListItems); - m_rCC.Invalidate(); + + if (bNeedsInvalidation) + m_rCC.Invalidate(); } OUString SwVbaContentControlListEntry::getValue() @@ -143,7 +154,8 @@ void SwVbaContentControlListEntry::Select() std::shared_ptr<SwContentControl> pCC = m_rCC.GetContentControl().GetContentControl(); assert(m_nZIndex < pCC->GetListItems().size()); pCC->SetSelectedListItem(m_nZIndex); - m_rCC.Invalidate(/*bKeepPlaceholderStatus=*/false); + pCC->SetShowingPlaceHolder(false); + m_rCC.Invalidate(); } // XHelperInterface diff --git a/sw/source/uibase/inc/wrtsh.hxx b/sw/source/uibase/inc/wrtsh.hxx index fb80f135237e..98b3d9038204 100644 --- a/sw/source/uibase/inc/wrtsh.hxx +++ b/sw/source/uibase/inc/wrtsh.hxx @@ -428,7 +428,12 @@ typedef bool (SwWrtShell::*FNSimpleMove)(); bool GotoField( const SwFormatField& rField ); - bool GotoContentControl(const SwFormatContentControl& rContentControl); + /** @param bOnlyRefresh: + * false: run default actions (e.g. toggle checkbox, remove placeholder content) + * true: do not alter the content control, just refresh the doc model + */ + bool GotoContentControl(const SwFormatContentControl& rContentControl, + bool bOnlyRefresh = false); // jump to the next / previous hyperlink - inside text and also // on graphics diff --git a/sw/source/uibase/wrtsh/wrtsh3.cxx b/sw/source/uibase/wrtsh/wrtsh3.cxx index 58204886933e..aa170d1374a4 100644 --- a/sw/source/uibase/wrtsh/wrtsh3.cxx +++ b/sw/source/uibase/wrtsh/wrtsh3.cxx @@ -93,7 +93,8 @@ bool SwWrtShell::GotoField( const SwFormatField& rField ) return bRet; } -bool SwWrtShell::GotoContentControl(const SwFormatContentControl& rContentControl) +bool SwWrtShell::GotoContentControl(const SwFormatContentControl& rContentControl, + bool bOnlyRefresh) { std::shared_ptr<SwContentControl> pContentControl = rContentControl.GetContentControl(); if (IsFrameSelected() && pContentControl && pContentControl->GetPicture()) @@ -124,23 +125,24 @@ bool SwWrtShell::GotoContentControl(const SwFormatContentControl& rContentContro (this->*m_fnKillSel)(nullptr, false); bool bRet = SwCursorShell::GotoFormatContentControl(rContentControl); + // Assume that once the placeholder is selected, the content is no longer the placeholder. + if (!bOnlyRefresh && pContentControl) + pContentControl->SetShowingPlaceHolder(false); + if (bRet && pContentControl && pContentControl->GetCheckbox()) { // Checkbox: GotoFormatContentControl() selected the old state. LockView(/*bViewLocked=*/true); - OUString aOldState; + OUString aOldState = GetCursorDescr(); OUString aNewState; if (pContentControl->GetChecked()) - { - aOldState = pContentControl->GetCheckedState(); - aNewState = pContentControl->GetUncheckedState(); - } + aNewState = bOnlyRefresh ? pContentControl->GetCheckedState() + : pContentControl->GetUncheckedState(); else - { - aOldState = pContentControl->GetUncheckedState(); - aNewState = pContentControl->GetCheckedState(); - } + aNewState = bOnlyRefresh ? pContentControl->GetUncheckedState() + : pContentControl->GetCheckedState(); + SwRewriter aRewriter; aRewriter.AddRule(UndoArg1, aOldState); aRewriter.AddRule(UndoArg2, SwResId(STR_YIELDS)); @@ -150,7 +152,8 @@ bool SwWrtShell::GotoContentControl(const SwFormatContentControl& rContentContro // Toggle the state. pContentControl->SetReadWrite(true); DelLeft(); - pContentControl->SetChecked(!pContentControl->GetChecked()); + if (!bOnlyRefresh) + pContentControl->SetChecked(!pContentControl->GetChecked()); Insert(aNewState); pContentControl->SetReadWrite(false);