Skip to content

Commit c9f91d4

Browse files
committed
Merge: sparkline endpoint ticks
2 parents 803c1c7 + 48437ec commit c9f91d4

1 file changed

Lines changed: 72 additions & 6 deletions

File tree

libs/FastSenseCompanion/InspectorPane.m

Lines changed: 72 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ function renderTag_(obj)
227227

228228
% Outer 5-row grid: title + table + sparkline + range-label + button.
229229
g = uigridlayout(obj.hContent_, [5 1]);
230-
g.RowHeight = {28, '1x', 78, 14, 32};
230+
g.RowHeight = {28, '1x', 92, 14, 32};
231231
g.ColumnWidth = {'1x'};
232232
g.Padding = [16 16 16 16]; g.RowSpacing = 6;
233233
g.BackgroundColor = t.WidgetBackground;
@@ -350,21 +350,27 @@ function renderTag_(obj)
350350

351351
function renderSparkline_(obj, tag)
352352
%RENDERSPARKLINE_ Render the trailing SparkWindowSec_ window of (X,Y).
353-
% Filters samples to the last 30 minutes, then plots. Stores
354-
% hSparkLine_ so refreshSparklineInPlace_ can update in place.
353+
% Shows 2-point X-axis ticks (start / end time) and 2-point Y-axis
354+
% ticks (min / max value). Stores hSparkLine_ so refreshSparklineInPlace_
355+
% can update XData/YData and tick labels in place.
355356
t = obj.Theme_;
356357
try
357358
if ~ismethod(tag, 'getXY'); obj.renderNoData_('No data'); return; end
358359
[tv, y] = tag.getXY();
359360
if isempty(tv) || isempty(y); obj.renderNoData_('No data'); return; end
360361
[tv, y] = obj.windowSparkData_(tv, y);
361362
obj.hSparkAxes_ = axes('Parent', obj.hSparkPanel_, ...
362-
'Units', 'normalized', 'Position', [0 0 1 1], ...
363-
'Color', t.WidgetBackground, 'XColor', t.WidgetBackground, ...
364-
'YColor', t.WidgetBackground, 'Box', 'off', 'XTick', [], 'YTick', []);
363+
'Units', 'normalized', 'Position', [0.22 0.26 0.75 0.70], ...
364+
'Color', t.WidgetBackground, ...
365+
'XColor', t.PlaceholderTextColor, ...
366+
'YColor', t.PlaceholderTextColor, ...
367+
'Box', 'off', 'FontSize', 8, ...
368+
'TickLength', [0.005 0.005], ...
369+
'TickDir', 'out');
365370
obj.hSparkLine_ = plot(obj.hSparkAxes_, tv, y, '-', ...
366371
'Color', t.LineColors{1}, 'LineWidth', 1);
367372
obj.fitSparkAxes_();
373+
obj.updateSparkTicks_(tv, y);
368374
try; obj.hSparkAxes_.Toolbar.Visible = 'off'; catch; end
369375
try; obj.hSparkAxes_.Interactions = []; catch; end
370376
obj.updateRangeLabel_(tv);
@@ -373,6 +379,65 @@ function renderSparkline_(obj, tag)
373379
end
374380
end
375381

382+
function updateSparkTicks_(obj, tv, y)
383+
%UPDATESPARKTICKS_ Set 2-point X (start/end time) and Y (min/max) ticks.
384+
if isempty(obj.hSparkAxes_) || ~isvalid(obj.hSparkAxes_); return; end
385+
if isempty(tv) || isempty(y); return; end
386+
try
387+
if numel(tv) >= 2 && tv(1) ~= tv(end)
388+
obj.hSparkAxes_.XTick = [tv(1), tv(end)];
389+
obj.hSparkAxes_.XTickLabel = {obj.formatXTick_(tv(1)), obj.formatXTick_(tv(end))};
390+
else
391+
obj.hSparkAxes_.XTick = tv(1);
392+
obj.hSparkAxes_.XTickLabel = {obj.formatXTick_(tv(1))};
393+
end
394+
yMin = min(y); yMax = max(y);
395+
if yMin < yMax
396+
obj.hSparkAxes_.YTick = [yMin, yMax];
397+
obj.hSparkAxes_.YTickLabel = {obj.formatYTick_(yMin), obj.formatYTick_(yMax)};
398+
else
399+
obj.hSparkAxes_.YTick = yMin;
400+
obj.hSparkAxes_.YTickLabel = {obj.formatYTick_(yMin)};
401+
end
402+
catch
403+
end
404+
end
405+
406+
function txt = formatXTick_(~, x)
407+
%FORMATXTICK_ Time-format an X value (posixtime / datenum / seconds).
408+
try
409+
if x > 1e9 % posixtime (Unix epoch seconds)
410+
txt = char(datetime(x, 'ConvertFrom', 'posixtime', ...
411+
'Format', 'HH:mm:ss'));
412+
elseif x > 7e5 % MATLAB datenum (days since 0000-01-01)
413+
txt = datestr(x, 'HH:MM:SS');
414+
elseif x >= 60
415+
mm = floor(x/60); ss = mod(x, 60);
416+
txt = sprintf('%d:%05.2f', mm, ss);
417+
else
418+
txt = sprintf('%.1fs', x);
419+
end
420+
catch
421+
txt = sprintf('%g', x);
422+
end
423+
end
424+
425+
function txt = formatYTick_(~, y)
426+
%FORMATYTICK_ Compact numeric format for the Y min/max ticks.
427+
a = abs(y);
428+
if a == 0
429+
txt = '0';
430+
elseif a >= 1000 || a < 0.01
431+
txt = sprintf('%.2g', y);
432+
elseif a >= 100
433+
txt = sprintf('%.0f', y);
434+
elseif a >= 10
435+
txt = sprintf('%.1f', y);
436+
else
437+
txt = sprintf('%.2f', y);
438+
end
439+
end
440+
376441
function [tv, y] = windowSparkData_(obj, tv, y)
377442
%WINDOWSPARKDATA_ Filter (X,Y) to the trailing SparkWindowSec_ horizon.
378443
% Assumes X is in seconds (datenum-day fallback handled below by
@@ -435,6 +500,7 @@ function refreshSparklineInPlace_(obj, tag)
435500
obj.hSparkLine_.XData = tv;
436501
obj.hSparkLine_.YData = y;
437502
obj.fitSparkAxes_();
503+
obj.updateSparkTicks_(tv, y);
438504
obj.updateRangeLabel_(tv);
439505
catch
440506
end

0 commit comments

Comments
 (0)