From 67ee03372c93ee39d813ef7408fac707ef742635 Mon Sep 17 00:00:00 2001 From: Hannes Suhr Date: Tue, 19 May 2026 08:40:25 +0200 Subject: [PATCH 1/3] fix(octave): guard isvalid in refreshActivePageWidgetsAfterResize_ Octave 7+ has no isvalid() for classdef handles, so the three unguarded isvalid(w) / isvalid(w.FastSenseObj) calls in DashboardEngine line 2022 and 2045/2048 broke Octave CI (test_engine_preview_nbuckets_reset). Inline an isOctave flag and short-circuit the check on Octave; behaviour unchanged on MATLAB. --- libs/Dashboard/DashboardEngine.m | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libs/Dashboard/DashboardEngine.m b/libs/Dashboard/DashboardEngine.m index 2849a48d..07f54b5b 100644 --- a/libs/Dashboard/DashboardEngine.m +++ b/libs/Dashboard/DashboardEngine.m @@ -2016,10 +2016,13 @@ function refreshActivePageWidgetsAfterResize_(obj) return; end ws = obj.activePageWidgets(); + isOctave = exist('OCTAVE_VERSION', 'builtin') ~= 0; % --- Pass 1: cheap data re-push --- for i = 1:numel(ws) w = ws{i}; - if isempty(w) || ~isvalid(w) + % Octave 7+ has no isvalid() for classdef handles, so treat + % as valid there and rely on downstream guards / try-catch. + if isempty(w) || (~isOctave && ~isvalid(w)) continue; end if ~w.Realized || isempty(w.hPanel) || ~ishandle(w.hPanel) @@ -2042,10 +2045,10 @@ function refreshActivePageWidgetsAfterResize_(obj) stillWhite = false; for i = 1:numel(ws) w = ws{i}; - if isempty(w) || ~isvalid(w) || ~isa(w, 'FastSenseWidget') + if isempty(w) || (~isOctave && ~isvalid(w)) || ~isa(w, 'FastSenseWidget') continue; end - if isempty(w.FastSenseObj) || ~isvalid(w.FastSenseObj) || ~w.FastSenseObj.IsRendered + if isempty(w.FastSenseObj) || (~isOctave && ~isvalid(w.FastSenseObj)) || ~w.FastSenseObj.IsRendered continue; end if ~obj.isWidgetLineWhite_(w) From 6667e6d13d5e073d85220acd2493e8bd1d7a49a1 Mon Sep 17 00:00:00 2001 From: Hannes Suhr Date: Tue, 19 May 2026 08:40:31 +0200 Subject: [PATCH 2/3] fix(octave): guard isvalid in FastSenseWidget.autoScaleY_ Octave 7+ has no isvalid() for classdef handles, so the unguarded isvalid(obj.FastSenseObj) check in autoScaleY_ broke every test that renders a FastSenseWidget or calls setYLimitMode (testDetectStaleWithFrozenSensor, testRefreshTriggers*, test_set_y_limit_mode_*, test_dashboard_preview_envelope). Inline an isOctave flag and short-circuit on Octave. --- libs/Dashboard/FastSenseWidget.m | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libs/Dashboard/FastSenseWidget.m b/libs/Dashboard/FastSenseWidget.m index 77c093a7..50d644ce 100644 --- a/libs/Dashboard/FastSenseWidget.m +++ b/libs/Dashboard/FastSenseWidget.m @@ -450,7 +450,11 @@ function autoScaleY_(obj, y) if obj.UserZoomedY return; end - if ~isempty(obj.FastSenseObj) && isvalid(obj.FastSenseObj) && ... + % Octave 7+ has no isvalid() for classdef handles, so treat the + % FastSense handle as valid there and let downstream property + % access surface real failures. + isOctave = exist('OCTAVE_VERSION', 'builtin') ~= 0; + if ~isempty(obj.FastSenseObj) && (isOctave || isvalid(obj.FastSenseObj)) && ... strcmp(obj.FastSenseObj.LiveViewMode, 'follow') return; end From e19b1138a9ea99c6b00b20d7a2150311d72af86e Mon Sep 17 00:00:00 2001 From: Hannes Suhr Date: Tue, 19 May 2026 08:40:36 +0200 Subject: [PATCH 3/3] fix(octave): guard isvalid in syncYLimitButtonsState_ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Octave 7+ has no isvalid() for classdef handles. Once autoScaleY_ is fixed, dashboard tests proceed to addYLimitButtons_ which calls syncYLimitButtonsState_ — the unguarded isvalid(w) on the cached widget handle would then throw. Inline isOctave and short-circuit on Octave. --- libs/Dashboard/DashboardLayout.m | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libs/Dashboard/DashboardLayout.m b/libs/Dashboard/DashboardLayout.m index a2e90370..5e1c72e4 100644 --- a/libs/Dashboard/DashboardLayout.m +++ b/libs/Dashboard/DashboardLayout.m @@ -1035,7 +1035,10 @@ function syncYLimitButtonsState_(bar, mode) inactiveBg = []; if isfield(ud, 'YLimitWidget') && ~isempty(ud.YLimitWidget) w = ud.YLimitWidget; - if isobject(w) && isvalid(w) && ... + % Octave 7+ has no isvalid() for classdef handles; treat as + % valid there and rely on the property-access guards below. + isOctave = exist('OCTAVE_VERSION', 'builtin') ~= 0; + if isobject(w) && (isOctave || isvalid(w)) && ... ~isempty(w.ParentTheme) && isstruct(w.ParentTheme) && ... isfield(w.ParentTheme, 'ToolbarBackground') inactiveBg = w.ParentTheme.ToolbarBackground;