Skip to content

Commit 35c1896

Browse files
committed
Refactor UIMonitor and Watchers
1 parent 293eb26 commit 35c1896

17 files changed

+1080
-943
lines changed

Source/ExcelDna.IntelliSense.Host/AddIn.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ public class AddIn : IExcelAddIn
1414
public void AutoOpen()
1515
{
1616
IntelliSenseServer.Register();
17-
// ExcelDna.Logging.LogDisplay.Show();
17+
ExcelDna.Logging.LogDisplay.Show();
18+
ExcelDna.Logging.LogDisplay.DisplayOrder = ExcelDna.Logging.DisplayOrder.NewestFirst;
1819
}
1920

2021
public void AutoClose()

Source/ExcelDna.IntelliSense.Host/ExcelDna.IntelliSense.Host-AddIn.xll.config

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,18 @@
11
<?xml version="1.0" encoding="utf-8" ?>
22
<configuration>
33
<system.diagnostics>
4+
<trace autoflush="true" indentsize="4"/>
45
<sources>
5-
<source name="ExcelDna.IntelliSense" switchValue="Off">
6+
<source name="ExcelDna.IntelliSense" switchValue="All">
7+
<listeners>
8+
<!--<remove name="Default" />-->
9+
<!--<add name="LogDisplay" type="ExcelDna.Logging.LogDisplayTraceListener,ExcelDna.Integration">
10+
<filter type="System.Diagnostics.EventTypeFilter" initializeData="All"/>
11+
</add>-->
12+
<add name="File" type="System.Diagnostics.TextWriterTraceListener" initializeData="ExcelDna.IntelliSense.log" >
13+
<filter type="System.Diagnostics.EventTypeFilter" initializeData="All"/>
14+
</add>
15+
</listeners>
616
</source>
717
</sources>
818
</system.diagnostics>

Source/ExcelDna.IntelliSense/ExcelDna.IntelliSense.csproj

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,24 +72,26 @@
7272
</ItemGroup>
7373
<ItemGroup>
7474
<Compile Include="FormattedText.cs" />
75-
<Compile Include="FormulaParser.cs" />
75+
<Compile Include="UIMonitor\FormulaEditWatcher.cs" />
76+
<Compile Include="UIMonitor\FormulaParser.cs" />
7677
<Compile Include="IntelliSenseDisplay.cs" />
7778
<Compile Include="IntelliSenseHelper.cs" />
7879
<Compile Include="IntelliSenseProvider.cs" />
7980
<Compile Include="IntelliSenseServer.cs" />
8081
<Compile Include="Logging.cs" />
82+
<Compile Include="UIMonitor\PopupListWatcher.cs" />
8183
<Compile Include="Properties\AssemblyInfo.cs" />
8284
<Compile Include="SingleThreadSynchronizationContext.cs" />
8385
<Compile Include="ToolTipForm.cs">
8486
<SubType>Form</SubType>
8587
</Compile>
86-
<Compile Include="UIMonitor.cs" />
87-
<Compile Include="Watchers.cs" />
88+
<Compile Include="UIMonitor\UIMonitor.cs" />
89+
<Compile Include="UIMonitor\WindowWatcher.cs" />
8890
<Compile Include="Win32Helper.cs" />
8991
<Compile Include="LoaderNotification.cs" />
9092
<Compile Include="WindowResizer.cs" />
91-
<Compile Include="WinEvents.cs" />
92-
<Compile Include="XlCall.cs" />
93+
<Compile Include="UIMonitor\WinEvents.cs" />
94+
<Compile Include="UIMonitor\XlCall.cs" />
9395
</ItemGroup>
9496
<ItemGroup>
9597
<EmbeddedResource Include="ToolTipForm.resx">

Source/ExcelDna.IntelliSense/IntelliSenseDisplay.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -256,9 +256,16 @@ void FormulaEditTextChange(string formulaPrefix, Rect editWindowBounds, Rect exc
256256
IntelliSenseFunctionInfo functionInfo;
257257
if (_functionInfoMap.TryGetValue(functionName, out functionInfo))
258258
{
259-
_argumentsToolTip.ShowToolTip(
260-
GetFunctionIntelliSense(functionInfo, currentArgIndex),
261-
(int)editWindowBounds.Left, (int)editWindowBounds.Bottom + 5);
259+
if (_argumentsToolTip != null)
260+
{
261+
_argumentsToolTip.ShowToolTip(
262+
GetFunctionIntelliSense(functionInfo, currentArgIndex),
263+
(int)editWindowBounds.Left, (int)editWindowBounds.Bottom + 5);
264+
}
265+
else
266+
{
267+
Logger.Display.Warn("FormulaEditTextChange with no arguments tooltip !?");
268+
}
262269
return;
263270
}
264271

Source/ExcelDna.IntelliSense/IntelliSenseProvider.cs

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ public void Refresh()
7171
if (regInfoResponse.Equals(ExcelError.ExcelErrorNA))
7272
{
7373
_regInfoNotAvailable = true;
74+
Logger.Provider.Verbose($"XllRegistrationInfo not available for {_xllPath}");
7475
return;
7576
}
7677

@@ -101,7 +102,9 @@ public IEnumerable<IntelliSenseFunctionInfo> GetFunctionInfos()
101102
if (regInfo == null)
102103
yield break;
103104

104-
for (int i = 0; i < regInfo.GetLength(0); i++)
105+
int regInfoCount = regInfo.GetLength(0);
106+
Logger.Provider.Verbose($"XllRegistrationInfo for {_xllPath}: {regInfoCount} registrations");
107+
for (int i = 0; i < regInfoCount; i++)
105108
{
106109
if (regInfo[i, 0] is ExcelEmpty)
107110
{
@@ -136,6 +139,7 @@ public IEnumerable<IntelliSenseFunctionInfo> GetFunctionInfos()
136139
ExcelSynchronizationContext _syncContextExcel;
137140
Dictionary<string, XllRegistrationInfo> _xllRegistrationInfos = new Dictionary<string, XllRegistrationInfo>();
138141
LoaderNotification _loaderNotification;
142+
bool _isDirty;
139143
public event EventHandler Invalidate;
140144

141145
public ExcelDnaIntelliSenseProvider()
@@ -158,6 +162,7 @@ public void Initialize()
158162
{
159163
if (!_xllRegistrationInfos.ContainsKey(xllPath))
160164
{
165+
Logger.Provider.Verbose($"ExcelDnaIntelliSenseProvider.Initialize: Adding XllRegistrationInfo for {xllPath}");
161166
XllRegistrationInfo regInfo = new XllRegistrationInfo(xllPath);
162167
_xllRegistrationInfos[xllPath] = regInfo;
163168
regInfo.Refresh();
@@ -177,16 +182,25 @@ public void Refresh()
177182
{
178183
regInfo.Refresh();
179184
}
185+
_isDirty = false;
180186
}
181187
}
182188

183189
// May be called from any thread
184190
public IList<IntelliSenseFunctionInfo> GetFunctionInfos()
185191
{
192+
IList<IntelliSenseFunctionInfo> functionInfos;
186193
lock (_xllRegistrationInfos)
187194
{
188-
return _xllRegistrationInfos.Values.SelectMany(ri => ri.GetFunctionInfos()).ToList();
195+
functionInfos = _xllRegistrationInfos.Values.SelectMany(ri => ri.GetFunctionInfos()).ToList();
189196
}
197+
Logger.Provider.Verbose("ExcelDnaIntelliSenseProvider.GetFunctionInfos Begin");
198+
foreach (var info in functionInfos)
199+
{
200+
Logger.Provider.Verbose($"\t{info.FunctionName}({info.ArgumentList.Count}) - {info.Description} ");
201+
}
202+
Logger.Provider.Verbose("ExcelDnaIntelliSenseProvider.GetFunctionInfos End");
203+
return functionInfos;
190204
}
191205

192206
#endregion
@@ -195,7 +209,7 @@ public IList<IntelliSenseFunctionInfo> GetFunctionInfos()
195209
// TODO: Consider Load/Unload done when AddIns is enumerated...
196210
void loaderNotification_LoadNotification(object sender, LoaderNotification.NotificationEventArgs e)
197211
{
198-
Debug.Print($"@>@>@>@> LoadNotification: {e.Reason} - {e.FullDllName}");
212+
// Debug.Print($"@>@>@>@> LoadNotification: {e.Reason} - {e.FullDllName}");
199213
if (e.FullDllName.EndsWith(".xll", StringComparison.OrdinalIgnoreCase))
200214
_syncContextExcel.Post(ProcessLoadNotification, e);
201215
}
@@ -207,6 +221,9 @@ void ProcessLoadNotification(object state)
207221
// we might want to introduce a delay here, so that the .xll can complete loading...
208222
var notification = (LoaderNotification.NotificationEventArgs)state;;
209223
var xllPath = notification.FullDllName;
224+
225+
Logger.Provider.Verbose($"ExcelDnaIntelliSenseProvider.ProcessLoadNotification {notification}, {xllPath}");
226+
210227
lock (_xllRegistrationInfos)
211228
{
212229
XllRegistrationInfo regInfo;
@@ -217,12 +234,18 @@ void ProcessLoadNotification(object state)
217234
regInfo = new XllRegistrationInfo(xllPath);
218235
_xllRegistrationInfos[xllPath] = regInfo;
219236
//regInfo.Refresh(); // Rather not.... so that we don't even try during the AddIns enumeration... OnInvalidate will lead to Refresh()
220-
OnInvalidate();
237+
238+
if (!_isDirty)
239+
{
240+
_isDirty = true;
241+
_syncContextExcel.Post(OnInvalidate, null);
242+
}
221243
}
222244
}
223245
else if (notification.Reason == LoaderNotification.Reason.Unloaded)
224246
{
225247
_xllRegistrationInfos.Remove(xllPath);
248+
// Not too worried about cleaning up
226249
// OnInvalidate();
227250
}
228251
}
@@ -247,7 +270,7 @@ IEnumerable<string> GetLoadedXllPaths()
247270
}
248271
}
249272

250-
void OnInvalidate()
273+
void OnInvalidate(object _unused_)
251274
{
252275
Invalidate?.Invoke(this, EventArgs.Empty);
253276
}

Source/ExcelDna.IntelliSense/IntelliSenseServer.cs

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ namespace ExcelDna.IntelliSense
4747
// REMEMBER: COM events are not necessarily safe macro contexts.
4848
public static class IntelliSenseServer
4949
{
50-
const string ServerVersion = "0.0.1"; // TODO: Define and manage this somewhere else
50+
const string ServerVersion = "0.0.2"; // TODO: Define and manage this somewhere else
5151

5252
// NOTE: Do not change these constants in custom versions.
5353
// They are part of the co-operative safety mechanism allowing different add-ins providing IntelliSense to work together safely.
@@ -76,10 +76,12 @@ public static class IntelliSenseServer
7676
// Called directly from AutoOpen.
7777
public static void Register()
7878
{
79+
TraceLogger.Initialize();
80+
81+
Logger.Initialization.Info($"IntelliSenseServer.Register Begin: Version {ServerVersion} in {AppDomain.CurrentDomain.FriendlyName}");
7982
if (IsDisabled())
8083
return;
8184

82-
TraceLogger.Initialize();
8385
RegisterControlFunction();
8486
PublishRegistration();
8587

@@ -95,6 +97,10 @@ public static void Register()
9597
// We're newer - deactivate the active server and activate ourselves.
9698
shouldActivate = true;
9799
}
100+
else
101+
{
102+
Logger.Initialization.Info($"IntelliSenseServer not being activated now. Active Version: {activeInfo.Version}");
103+
}
98104
// Else we're not activating - there is an active server and it is the same version or newer
99105
// TODO: Tell it to load our UDFs somehow - maybe call a hidden macro?
100106

@@ -104,6 +110,7 @@ public static void Register()
104110
}
105111

106112
AppDomain.CurrentDomain.DomainUnload += CurrentDomain_DomainUnload;
113+
Logger.Initialization.Info("IntelliSenseServer.Register End");
107114
}
108115

109116
// DomainUnload runs when AutoClose() would run on the add-in.
@@ -138,9 +145,9 @@ internal static bool Activate()
138145
// TODO: Perhaps also register macro to trigger updates
139146
return true;
140147
}
141-
catch (Exception /*ex*/)
148+
catch (Exception ex)
142149
{
143-
// TOOD: Log
150+
Logger.Initialization.Error($"IntelliSenseServer.Activate failed: {ex}");
144151
return false;
145152
}
146153
}
@@ -175,9 +182,16 @@ static bool IsDisabled()
175182
var environmentDisabled = Environment.GetEnvironmentVariable(DisabledVersionsVariable) as string;
176183

177184
var thisVersion = ServerVersion;
178-
return IsVersionMatch(thisVersion, machineDisabled) ||
179-
IsVersionMatch(thisVersion, userDisabled) ||
180-
IsVersionMatch(thisVersion, environmentDisabled);
185+
var isDisabled = IsVersionMatch(thisVersion, machineDisabled) ||
186+
IsVersionMatch(thisVersion, userDisabled) ||
187+
IsVersionMatch(thisVersion, environmentDisabled);
188+
189+
if (isDisabled)
190+
{
191+
Logger.Initialization.Info($"IntelliSenseServer version {thisVersion} is disabled. MachineDisabled: {machineDisabled}, UserDisabled: {userDisabled}, EnvironmentDisabled: {environmentDisabled}");
192+
}
193+
194+
return isDisabled;
181195
}
182196

183197
// Attempts to activate the server described by registrationInfo

Source/ExcelDna.IntelliSense/IntellisenseHelper.cs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,19 @@ class IntelliSenseHelper : IDisposable
2020

2121
public IntelliSenseHelper()
2222
{
23+
Logger.Initialization.Verbose("IntelliSenseHelper Constructor Begin");
2324
_syncContextMain = new WindowsFormsSynchronizationContext();
2425
_uiMonitor = new UIMonitor(_syncContextMain);
26+
_display = new IntelliSenseDisplay(_syncContextMain, _uiMonitor);
2527

26-
IIntelliSenseProvider excelDnaProvider = new ExcelDnaIntelliSenseProvider();
27-
_providers.Add(excelDnaProvider);
28-
IIntelliSenseProvider workbookProvider = new WorkbookIntelliSenseProvider();
29-
_providers.Add(workbookProvider);
28+
_providers = new List<IIntelliSenseProvider>
29+
{
30+
new ExcelDnaIntelliSenseProvider(),
31+
new WorkbookIntelliSenseProvider()
32+
};
3033

31-
_display = new IntelliSenseDisplay(_syncContextMain, _uiMonitor);
3234
RegisterIntellisense();
35+
Logger.Initialization.Verbose("IntelliSenseHelper Constructor End");
3336
}
3437

3538
void RegisterIntellisense()
@@ -42,7 +45,6 @@ void RegisterIntellisense()
4245
}
4346
}
4447

45-
// Must be raised on the main thread, in a macro context
4648
// We need to call Refresh on the main thread in a macro context,
4749
// and then GetFunctionInfos() to update the Display
4850
void Provider_Invalidate(object sender, EventArgs e)

Source/ExcelDna.IntelliSense/Logging.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ namespace ExcelDna.IntelliSense
5151

5252
// NOTE: To simplify configuration (so that we provide one TraceSource per referenced assembly) and still allow some grouping
5353
// we use the EventId to define a trace event classification.
54-
// These names are not surfaces to the Trace Listeners - just the IDs, so we should document them.
54+
// These names are not surfaced to the Trace Listeners - just the IDs, so we should document them.
5555
enum IntelliSenseTraceEventId
5656
{
5757
Initialization = 1,

0 commit comments

Comments
 (0)