Skip to content

Commit cfb6bd3

Browse files
web: disable Tcl console and add empty states in static HTML reports
Signed-off-by: Jorge Ferreira <jorge.ferreira@precisioninno.com>
1 parent d4c534c commit cfb6bd3

7 files changed

Lines changed: 83 additions & 6 deletions

File tree

src/web/src/charts-widget.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// Canvas-based slack histogram widget.
55

66
import { getThemeColors } from './theme.js';
7+
import { isStaticMode } from './ui-utils.js';
78

89
// Layout margins (pixels)
910
export const kLeftMargin = 60;
@@ -155,6 +156,9 @@ export class ChartsWidget {
155156
this._updateBtn = document.createElement('button');
156157
this._updateBtn.className = 'timing-btn';
157158
this._updateBtn.textContent = 'Update';
159+
if (isStaticMode(this._app)) {
160+
this._updateBtn.style.display = 'none';
161+
}
158162

159163
this._statusLabel = document.createElement('span');
160164
this._statusLabel.className = 'timing-path-count';
@@ -224,6 +228,10 @@ export class ChartsWidget {
224228

225229
this._ctx = this._canvas.getContext('2d');
226230
this._bindEvents();
231+
232+
if (isStaticMode(this._app)) {
233+
setTimeout(() => this.update(), 0);
234+
}
227235
}
228236

229237
_bindEvents() {
@@ -365,7 +373,10 @@ export class ChartsWidget {
365373
ctx.font = '14px monospace';
366374
ctx.textAlign = 'center';
367375
ctx.textBaseline = 'middle';
368-
ctx.fillText('Click "Update" to load histogram', w / 2, h / 2);
376+
const msg = isStaticMode(this._app)
377+
? 'No histogram data available'
378+
: 'Click "Update" to load histogram';
379+
ctx.fillText(msg, w / 2, h / 2);
369380
return;
370381
}
371382

src/web/src/clock-tree-widget.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// Canvas-based clock tree viewer widget.
55

66
import { getThemeColors } from './theme.js';
7+
import { isStaticMode } from './ui-utils.js';
78

89
export const kNodeSpacing = 24; // pixels between adjacent leaf bins
910
export const kNodeSize = 10; // base node shape size in pixels
@@ -189,6 +190,9 @@ export class ClockTreeWidget {
189190
this._updateBtn = document.createElement('button');
190191
this._updateBtn.className = 'timing-btn';
191192
this._updateBtn.textContent = 'Update';
193+
if (isStaticMode(this._app)) {
194+
this._updateBtn.style.display = 'none';
195+
}
192196
this._fitBtn = document.createElement('button');
193197
this._fitBtn.className = 'timing-btn';
194198
this._fitBtn.textContent = 'Fit';
@@ -220,6 +224,10 @@ export class ClockTreeWidget {
220224

221225
this._ctx = this._canvas.getContext('2d');
222226
this._bindEvents();
227+
228+
if (isStaticMode(this._app)) {
229+
setTimeout(() => this.update(), 0);
230+
}
223231
}
224232

225233
_fit() {
@@ -393,8 +401,10 @@ export class ClockTreeWidget {
393401
ctx.fillStyle = tc.canvasText;
394402
ctx.font = '14px monospace';
395403
ctx.textAlign = 'center';
396-
ctx.fillText('Click "Update" to load clock tree data',
397-
w / 2, h / 2);
404+
const msg = isStaticMode(this._app)
405+
? 'No clock tree data available'
406+
: 'Click "Update" to load clock tree data';
407+
ctx.fillText(msg, w / 2, h / 2);
398408
return;
399409
}
400410

src/web/src/hierarchy-browser.js

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// Hierarchy browser widget — module tree with coloring.
55

66
import { CheckboxTreeModel } from './checkbox-tree-model.js';
7-
import { makeResizableHeaders } from './ui-utils.js';
7+
import { isStaticMode, makeResizableHeaders } from './ui-utils.js';
88

99
const COLS = [
1010
'Instance', 'Module', 'Instances', 'Macros', 'Modules',
@@ -35,7 +35,7 @@ export class HierarchyBrowser {
3535
app.hierarchyBrowser = this;
3636

3737
// Auto-load in static mode (data is already cached).
38-
if (app.websocketManager && app.websocketManager.isStaticMode) {
38+
if (isStaticMode(app)) {
3939
this.update();
4040
}
4141
}
@@ -51,6 +51,9 @@ export class HierarchyBrowser {
5151
this._updateBtn = document.createElement('button');
5252
this._updateBtn.className = 'timing-btn';
5353
this._updateBtn.textContent = 'Update';
54+
if (isStaticMode(this._app)) {
55+
this._updateBtn.style.display = 'none';
56+
}
5457

5558
this._statusLabel = document.createElement('span');
5659
this._statusLabel.className = 'timing-path-count';
@@ -352,6 +355,20 @@ export class HierarchyBrowser {
352355

353356
tbody.appendChild(tr);
354357
}
358+
359+
if (this._rows.length === 0) {
360+
const tr = document.createElement('tr');
361+
const td = document.createElement('td');
362+
td.colSpan = COLS.length;
363+
td.style.textAlign = 'center';
364+
td.style.color = 'var(--fg-secondary)';
365+
td.textContent = isStaticMode(this._app) ?
366+
'No hierarchy data available' :
367+
'Click "Update" to load hierarchy';
368+
tr.appendChild(td);
369+
tbody.appendChild(tr);
370+
}
371+
355372
this._table.appendChild(tbody);
356373
makeResizableHeaders(this._table);
357374
}

src/web/src/main.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { ClockTreeWidget } from './clock-tree-widget.js';
1010
import { ChartsWidget } from './charts-widget.js';
1111
import { HierarchyBrowser } from './hierarchy-browser.js';
1212
import { createInspectorPanel } from './inspector.js';
13+
import { isStaticMode } from './ui-utils.js';
1314
import { populateDisplayControls } from './display-controls.js';
1415
import { createMenuBar } from './menu-bar.js';
1516
import { RulerManager } from './ruler.js';
@@ -496,6 +497,18 @@ function createTclConsole(container) {
496497
container.element.appendChild(el);
497498

498499
app.tclOutputEl = el.querySelector('.tcl-output');
500+
501+
if (isStaticMode(app)) {
502+
el.querySelector('.tcl-input-row').style.display = 'none';
503+
const notice = document.createElement('span');
504+
notice.className = 'tcl-static-notice';
505+
notice.setAttribute('role', 'status');
506+
notice.setAttribute('aria-live', 'polite');
507+
notice.textContent = 'Tcl console is not available in saved reports.';
508+
app.tclOutputEl.appendChild(notice);
509+
return;
510+
}
511+
499512
const input = el.querySelector('.tcl-input');
500513
const completer = new TclCompleter(input, app.websocketManager);
501514

src/web/src/style.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,10 @@ html, body {
726726
.tcl-error {
727727
color: var(--error-text);
728728
}
729+
.tcl-static-notice {
730+
color: var(--fg-muted);
731+
font-style: italic;
732+
}
729733
.tcl-input-row {
730734
display: flex;
731735
align-items: center;

src/web/src/timing-widget.js

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
// Timing report widget — path summary + detail tables.
55

6-
import { makeResizableHeaders } from './ui-utils.js';
6+
import { isStaticMode, makeResizableHeaders } from './ui-utils.js';
77

88
export class TimingWidget {
99
constructor(app, redrawAllLayers) {
@@ -31,6 +31,9 @@ export class TimingWidget {
3131
this._updateBtn = document.createElement('button');
3232
this._updateBtn.className = 'timing-btn';
3333
this._updateBtn.textContent = 'Update';
34+
if (isStaticMode(this._app)) {
35+
this._updateBtn.style.display = 'none';
36+
}
3437

3538
this._pathCountLabel = document.createElement('span');
3639
this._pathCountLabel.className = 'timing-path-count';
@@ -77,6 +80,10 @@ export class TimingWidget {
7780
this.element = el;
7881

7982
this._bindEvents();
83+
84+
if (isStaticMode(this._app)) {
85+
setTimeout(() => this.update(), 0);
86+
}
8087
}
8188

8289
_makeTab(label, active) {
@@ -270,6 +277,20 @@ export class TimingWidget {
270277
tr.addEventListener('click', () => this._selectPathRow(idx));
271278
tbody.appendChild(tr);
272279
});
280+
281+
if (paths.length === 0) {
282+
const tr = document.createElement('tr');
283+
const td = document.createElement('td');
284+
td.colSpan = TimingWidget.PATH_COLS.length;
285+
td.style.textAlign = 'center';
286+
td.style.color = 'var(--fg-secondary)';
287+
td.textContent = isStaticMode(this._app) ?
288+
'No timing data available' :
289+
'Click "Update" to load timing paths';
290+
tr.appendChild(td);
291+
tbody.appendChild(tr);
292+
}
293+
273294
this._pathTable.appendChild(tbody);
274295

275296
// Restore previous widths if available, otherwise compute fresh.

src/web/src/web.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1233,6 +1233,7 @@ window.__STATIC_CACHE__ = {
12331233
</script>
12341234
<script type="module">
12351235
import { GoldenLayout, LayoutConfig } from 'https://esm.sh/golden-layout@2.6.0';
1236+
import * as THREE from 'https://esm.sh/three@0.160.0';
12361237
)" << kReportJS
12371238
<< R"(
12381239
</script>

0 commit comments

Comments
 (0)