Skip to content

Commit 4af572a

Browse files
committed
Rework update event filtering to allow multiple listeners
1 parent 049e001 commit 4af572a

File tree

2 files changed

+36
-17
lines changed

2 files changed

+36
-17
lines changed

Source/ExcelDna.IntelliSense/IntelliSenseDisplay.cs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,31 +53,37 @@ public IntelliSenseDisplay(SynchronizationContext syncContextMain, UIMonitor uiM
5353

5454
_syncContextMain = syncContextMain;
5555
_uiMonitor = uiMonitor;
56-
_uiMonitor.StateUpdateFilter = StateUpdateFilter;
57-
_uiMonitor.StateUpdate = StateUpdate;
56+
_uiMonitor.StateUpdatePreview += StateUpdatePreview;
57+
_uiMonitor.StateUpdate += StateUpdate;
5858
}
5959

6060
// This runs on the UIMonitor's automation thread
61-
bool StateUpdateFilter(UIStateUpdate update)
61+
// Allows us to enable the update to be raised on main thread
62+
// Might be raised on the main thread even if we don't enable it (other listeners might enable)
63+
void StateUpdatePreview(object sender, UIStateUpdate update)
6264
{
65+
bool enable;
6366
if (update.Update == UIStateUpdate.UpdateType.FormulaEditTextChange)
6467
{
6568
var fe = (UIState.FormulaEdit)update.NewState;
66-
return ShouldProcessFormulaEditTextChange(fe.FormulaPrefix);
69+
enable = ShouldProcessFormulaEditTextChange(fe.FormulaPrefix);
6770
}
6871
else if (update.Update == UIStateUpdate.UpdateType.FunctionListSelectedItemChange)
6972
{
7073
var fl = (UIState.FunctionList)update.NewState;
71-
return ShouldProcessFunctionListSelectedItemChange(fl.SelectedItemText);
74+
enable = ShouldProcessFunctionListSelectedItemChange(fl.SelectedItemText);
7275
}
7376
else
7477
{
75-
return true; // allow the update event to be raised
78+
enable = true; // allow the update event to be raised by default
7679
}
80+
81+
if (enable)
82+
update.EnableUpdateEvent();
7783
}
7884

7985
// This runs on the main thread
80-
void StateUpdate(UIStateUpdate update)
86+
void StateUpdate(object sender, UIStateUpdate update)
8187
{
8288
Debug.Print($"STATE UPDATE ({update.Update}): {update.OldState} => {update.NewState}");
8389

Source/ExcelDna.IntelliSense/UIMonitor.cs

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -329,15 +329,23 @@ public enum UpdateType
329329
SelectDataSourceMainWindowChange,
330330
SelectDataSourceHide
331331
}
332-
public UIState OldState;
333-
public UIState NewState;
334-
public UpdateType Update;
332+
public UIState OldState { get; }
333+
public UIState NewState { get; }
334+
public UpdateType Update { get; }
335+
public bool IsEnabled { get; private set; } // Should this update be raised on the main thread - allows preview event to filter out some events
335336

336337
public UIStateUpdate(UIState oldState, UIState newState, UpdateType update)
337338
{
338339
OldState = oldState;
339340
NewState = newState;
340341
Update = update;
342+
IsEnabled = false;
343+
}
344+
345+
// Call this to allow the update event (on the main thread) to be raised
346+
public void EnableUpdateEvent()
347+
{
348+
IsEnabled = true;
341349
}
342350
}
343351

@@ -355,8 +363,8 @@ class UIMonitor : IDisposable
355363
PopupListWatcher _popupListWatcher;
356364

357365
public UIState CurrentState = UIState.ReadyState;
358-
public Func<UIStateUpdate, bool> StateUpdateFilter; // Always called on the automation thread
359-
public Action<UIStateUpdate> StateUpdate; // Always posted to the main thread
366+
public EventHandler<UIStateUpdate> StateUpdatePreview; // Always called on the automation thread
367+
public EventHandler<UIStateUpdate> StateUpdate; // Always posted to the main thread
360368

361369
public UIMonitor(SynchronizationContext syncContextMain)
362370
{
@@ -479,17 +487,22 @@ UIState ReadCurrentState()
479487
}
480488

481489
// Filter the states changes (on the automation thread) and then raise changes (on the main thread)
482-
// TODO: We might short-cut the update type too, for the common FormulaEdit and SelectItemChange cases
483490
void OnStateChanged(UIState newStateOrNull = null)
484491
{
485492
var oldState = CurrentState;
486493
if (newStateOrNull == null)
487494
newStateOrNull = ReadCurrentState();
488495
CurrentState = newStateOrNull;
489496

490-
var updates = UIState.GetUpdates(oldState, CurrentState)
491-
.Where(StateUpdateFilter)
492-
.ToList();
497+
var updates = new List<UIStateUpdate>(); // TODO: Improve perf for common single-update case
498+
foreach (var update in UIState.GetUpdates(oldState, CurrentState))
499+
{
500+
// First we raise the preview event on this thread
501+
// allowing listeners to enable the main-thread event for this update
502+
StateUpdatePreview?.Invoke(this, update);
503+
if (update.IsEnabled)
504+
updates.Add(update);
505+
}
493506
if (updates.Count > 0)
494507
_syncContextMain.Post(RaiseStateUpdates, updates);
495508
}
@@ -535,7 +548,7 @@ void RaiseStateUpdates(object updates)
535548
{
536549
foreach (var update in (List<UIStateUpdate>)updates)
537550
{
538-
StateUpdate(update);
551+
StateUpdate?.Invoke(this, update);
539552
}
540553
}
541554

0 commit comments

Comments
 (0)