From 794c1661d53e1f92e014a1527a168b01f5fddc73 Mon Sep 17 00:00:00 2001 From: mark-sil <83427558+mark-sil@users.noreply.github.com> Date: Tue, 4 Aug 2026 13:39:31 -0400 Subject: [PATCH] LT-21402: Part 3 - Move MasterRefresh to Pub/Sub (Insert/Delete) These two senders (InsertEntryDlgListener.DialogInsertItemInVector and RecordClerk.OnDeleteRecord) both update the cache directly (UOW + PropChanged), so when an XHTML document view is active, the Mediator's High-priority stop-when-handled intercept correctly satisfied the refresh with a fast content-only reload; the full master refresh was only needed in the other tools. Pub/Sub has no stop-when-handled, so the intercept is replaced with a two-stage refresh request. - New event RefreshCurrentView. The sender publishes it (window-scoped) with a ReturnObject; a subscriber that can satisfy the request by regenerating its own content sets ReturnValue. If no subscriber claims the request, the sender publishes MasterRefresh instead. - XhtmlDocView subscribes while it exists (Init/Dispose), i.e. exactly while its tool is the active content control - the subscription lifetime does the routing that colleague priority used to do. - XhtmlRecordDocView (the Lexicon Edit preview pane) deliberately does NOT subscribe: in Lexicon Edit these commands do the full refresh today, and that is preserved. Behavior is unchanged: content-only reload when a Dictionary, Reversal Indexes, or Classified Dictionary document view is active; full master refresh everywhere else. Co-Authored-By: Claude Fable 5 --- Src/Common/FwUtils/EventConstants.cs | 1 + .../LexTextControls/EntryDlgListener.cs | 9 +++++++- Src/xWorks/RecordClerk.cs | 11 ++++++--- Src/xWorks/XhtmlDocView.cs | 23 +++++++++++++++++++ 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/Src/Common/FwUtils/EventConstants.cs b/Src/Common/FwUtils/EventConstants.cs index 34283e7a4d..85990748a8 100644 --- a/Src/Common/FwUtils/EventConstants.cs +++ b/Src/Common/FwUtils/EventConstants.cs @@ -32,6 +32,7 @@ public static class EventConstants public const string PrepareToRefresh = "PrepareToRefresh"; public const string RecordNavigation = "RecordNavigation"; public const string RefreshCurrentList = "RefreshCurrentList"; + public const string RefreshCurrentView = "RefreshCurrentView"; public const string RefreshInterlin = "RefreshInterlin"; public const string RefreshPopupWindowFonts = "RefreshPopupWindowFonts"; public const string ReloadAreaTools = "ReloadAreaTools"; diff --git a/Src/LexText/LexTextControls/EntryDlgListener.cs b/Src/LexText/LexTextControls/EntryDlgListener.cs index 6928c5b16e..149c161ed0 100644 --- a/Src/LexText/LexTextControls/EntryDlgListener.cs +++ b/Src/LexText/LexTextControls/EntryDlgListener.cs @@ -96,8 +96,15 @@ private void DialogInsertItemInVector(object obj) bool newby; dlg.GetDialogInfo(out entry, out newby); // No need for a PropChanged here because InsertEntryDlg takes care of that. (LT-3608) + // Two-stage refresh: if the active content control can satisfy the request by + // regenerating its own content (the XHTML document views), skip the full refresh. + var refreshRequest = new ReturnObject(null); + Publisher.Publish(new PublisherParameterObject(EventConstants.RefreshCurrentView, refreshRequest, m_propertyTable.GetWindow())); + if (!refreshRequest.ReturnValue) + { + Publisher.Publish(new PublisherParameterObject(EventConstants.MasterRefresh, null, m_propertyTable.GetWindow())); + } #pragma warning disable 618 // suppress obsolete warning - m_mediator.SendMessage("MasterRefresh", null); m_mediator.SendMessage("JumpToRecord", entry.Hvo); #pragma warning restore 618 } diff --git a/Src/xWorks/RecordClerk.cs b/Src/xWorks/RecordClerk.cs index e3744ae20b..14a0df816d 100644 --- a/Src/xWorks/RecordClerk.cs +++ b/Src/xWorks/RecordClerk.cs @@ -1547,9 +1547,14 @@ private void DeleteRecord(object commandObject) } } } -#pragma warning disable 618 // suppress obsolete warning - m_mediator.SendMessage("MasterRefresh", null); -#pragma warning restore 618 + // Two-stage refresh: if the active content control can satisfy the request by + // regenerating its own content (the XHTML document views), skip the full refresh. + var refreshRequest = new ReturnObject(null); + Publisher.Publish(new PublisherParameterObject(EventConstants.RefreshCurrentView, refreshRequest, m_propertyTable.GetWindow())); + if (!refreshRequest.ReturnValue) + { + Publisher.Publish(new PublisherParameterObject(EventConstants.MasterRefresh, null, m_propertyTable.GetWindow())); + } } } } diff --git a/Src/xWorks/XhtmlDocView.cs b/Src/xWorks/XhtmlDocView.cs index ee10e63ecf..87ef129981 100644 --- a/Src/xWorks/XhtmlDocView.cs +++ b/Src/xWorks/XhtmlDocView.cs @@ -82,6 +82,7 @@ public override void Init(Mediator mediator, PropertyTable propertyTable, XmlNod } } Subscriber.Subscribe(EventConstants.DictionaryConfigured, RefreshAllContent, m_propertyTable.GetWindow()); + Subscriber.Subscribe(EventConstants.RefreshCurrentView, RefreshCurrentView, m_propertyTable.GetWindow()); } protected override void Dispose(bool disposing) @@ -93,6 +94,7 @@ protected override void Dispose(bool disposing) if (disposing) { Subscriber.Unsubscribe(EventConstants.DictionaryConfigured, RefreshAllContent); + Subscriber.Unsubscribe(EventConstants.RefreshCurrentView, RefreshCurrentView); } base.Dispose(disposing); } @@ -1323,6 +1325,27 @@ public void OnMasterRefresh(object sender) RefreshAllContent(null); } + /// + /// First stage of a sender's two-stage refresh request: while this view is the active + /// content control it claims the request and satisfies it by regenerating its own + /// content, so the sender skips the full master refresh. + /// + private void RefreshCurrentView(object obj) + { + if (!(obj is ReturnObject retObj)) + { + Debug.Assert(false, "Received unexpected object type."); + return; + } + // Return if already handled by another Subscriber. + if (retObj.ReturnValue) + { + return; + } + RefreshAllContent(null); + retObj.ReturnValue = true; + } + /// /// Regenerate this view's XHTML content, ensuring the selected publication is valid for /// the current configuration. Subscribed to the Pub/Sub DictionaryConfigured event.