Skip to content

Commit 4fefcf9

Browse files
committed
Merge fix: bypass TagRegistry.get for selected-tag resolution
2 parents 05fd84b + 1a90cc5 commit 4fefcf9

2 files changed

Lines changed: 76 additions & 8 deletions

File tree

libs/FastSenseCompanion/FastSenseCompanion.m

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -408,13 +408,43 @@ function resolveInspectorState_(obj)
408408
%RESOLVEINSPECTORSTATE_ Compute (state, payload) and fire InspectorStateChanged.
409409
% Single notify point for the inspector. Inspector subscribes via the
410410
% InspectorStateChanged listener wired in the constructor / setProject.
411+
%
412+
% Resolution strategy: prefer tag HANDLES from the catalog snapshot
413+
% (CatalogPane_.getSelectedTags()) over a TagRegistry.get() round
414+
% trip. The catalog already has resolved Tag handles; using them
415+
% directly bypasses any drift between the catalog snapshot and
416+
% the TagRegistry singleton's current state (e.g. cooling.health
417+
% visible in catalog but missing from get() — a real bug seen in
418+
% the industrial plant demo). Keys without a matching handle in
419+
% the catalog snapshot are silently dropped.
411420
try
412-
[state, payload] = inspectorResolveState( ...
413-
obj.LastInteraction_, ...
414-
obj.SelectedTagKeys_, ...
415-
obj.SelectedDashboardIdx_, ...
416-
obj.Engines_, ...
417-
obj.Registry_);
421+
state = '';
422+
payload = struct();
423+
tags = obj.CatalogPane_.getSelectedTags();
424+
nTags = numel(tags);
425+
426+
if nTags == 1
427+
state = 'tag';
428+
payload = struct('tag', tags{1}, ...
429+
'tagKeys', {obj.SelectedTagKeys_});
430+
elseif nTags >= 2
431+
state = 'multitag';
432+
payload = struct('tags', {tags}, ...
433+
'tagKeys', {obj.SelectedTagKeys_});
434+
elseif strcmp(obj.LastInteraction_, 'dashboard') ...
435+
&& isnumeric(obj.SelectedDashboardIdx_) ...
436+
&& isscalar(obj.SelectedDashboardIdx_) ...
437+
&& obj.SelectedDashboardIdx_ > 0 ...
438+
&& obj.SelectedDashboardIdx_ <= numel(obj.Engines_)
439+
state = 'dashboard';
440+
payload = struct('dashboard', ...
441+
obj.Engines_{obj.SelectedDashboardIdx_});
442+
else
443+
state = 'welcome';
444+
payload = struct('nTags', nTags, ...
445+
'nDashboards', numel(obj.Engines_));
446+
end
447+
418448
ed = InspectorStateEventData(state, payload);
419449
notify(obj, 'InspectorStateChanged', ed);
420450
catch err
@@ -435,9 +465,27 @@ function onOpenAdHocPlotRequested_(obj, ~, evt)
435465
try
436466
keys = evt.TagKeys;
437467
mode = evt.Mode;
438-
tags = cell(1, numel(keys));
468+
% Prefer the catalog snapshot's already-resolved Tag handles
469+
% over a TagRegistry.get() round-trip (catalog/registry can
470+
% drift; see resolveInspectorState_).
471+
allTags = obj.CatalogPane_.getSelectedTags();
472+
allKeys = obj.SelectedTagKeys_;
473+
tags = {};
439474
for k = 1:numel(keys)
440-
tags{k} = obj.Registry_.get(keys{k});
475+
matched = false;
476+
for j = 1:numel(allTags)
477+
if strcmp(allKeys{j}, keys{k})
478+
tags{end+1} = allTags{j}; %#ok<AGROW>
479+
matched = true;
480+
break;
481+
end
482+
end
483+
if ~matched
484+
% Last-resort registry fallback (still wrapped in
485+
% the outer try/catch so a missing key surfaces as
486+
% uialert instead of crashing the figure callback).
487+
tags{end+1} = obj.Registry_.get(keys{k}); %#ok<AGROW>
488+
end
441489
end
442490
[~, skipped] = openAdHocPlot(tags, mode, obj.Theme);
443491
if ~isempty(skipped)

libs/FastSenseCompanion/TagCatalogPane.m

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,26 @@ function refresh(obj)
210210
keys = obj.SelectedKeys_;
211211
end
212212

213+
function tags = getSelectedTags(obj)
214+
%GETSELECTEDTAGS Return the current selection as a cell of Tag handles.
215+
% Resolved against the catalog's own snapshot (AllTags_) — does NOT
216+
% round-trip through TagRegistry.get(), so the inspector is robust
217+
% against registry state changes (clear/re-register/etc.) that can
218+
% happen between catalog snapshot and click. Keys not present in
219+
% AllTags_ are silently skipped (defensive).
220+
tags = {};
221+
for k = 1:numel(obj.SelectedKeys_)
222+
key = obj.SelectedKeys_{k};
223+
for j = 1:numel(obj.AllTags_)
224+
t = obj.AllTags_{j};
225+
if strcmp(t.Key, key)
226+
tags{end+1} = t; %#ok<AGROW>
227+
break;
228+
end
229+
end
230+
end
231+
end
232+
213233
function deselectKey(obj, key)
214234
%DESELECTKEY Remove a single key from the selection set and fire TagSelectionChanged.
215235
% key — char tag key (e.g., 'pressure_a')

0 commit comments

Comments
 (0)