Virtualize instance and net lists for large schematic performance
This commit is contained in:
parent
3cb6feeb15
commit
559ff51013
@ -4,6 +4,8 @@ const SCHEMA_URL = "/schemeta.schema.json";
|
||||
const NET_CLASSES = ["power", "ground", "signal", "analog", "differential", "clock", "bus"];
|
||||
const PIN_SIDES = ["left", "right", "top", "bottom"];
|
||||
const PIN_TYPES = ["power_in", "power_out", "input", "output", "bidirectional", "passive", "analog", "ground"];
|
||||
const LIST_ROW_HEIGHT = 36;
|
||||
const LIST_OVERSCAN_ROWS = 8;
|
||||
|
||||
const state = {
|
||||
model: null,
|
||||
@ -721,6 +723,26 @@ function resolveLabelCollisions(svg) {
|
||||
}
|
||||
}
|
||||
|
||||
function renderVirtualList(listEl, allItems, renderRow, rowHeight = LIST_ROW_HEIGHT) {
|
||||
const items = Array.isArray(allItems) ? allItems : [];
|
||||
if (!items.length) {
|
||||
listEl.innerHTML = "";
|
||||
return;
|
||||
}
|
||||
|
||||
const viewportHeight = Math.max(rowHeight * 4, listEl.clientHeight || 230);
|
||||
const scrollTop = listEl.scrollTop;
|
||||
const total = items.length;
|
||||
const visibleRows = Math.ceil(viewportHeight / rowHeight);
|
||||
const start = Math.max(0, Math.floor(scrollTop / rowHeight) - LIST_OVERSCAN_ROWS);
|
||||
const end = Math.min(total, start + visibleRows + LIST_OVERSCAN_ROWS * 2);
|
||||
const topPad = start * rowHeight;
|
||||
const bottomPad = (total - end) * rowHeight;
|
||||
|
||||
const rows = items.slice(start, end).map(renderRow).join("");
|
||||
listEl.innerHTML = `<li class="listSpacer" style="height:${topPad}px"></li>${rows}<li class="listSpacer" style="height:${bottomPad}px"></li>`;
|
||||
}
|
||||
|
||||
function renderInstances() {
|
||||
if (!state.model) {
|
||||
el.instanceList.innerHTML = "";
|
||||
@ -730,12 +752,15 @@ function renderInstances() {
|
||||
const q = el.instanceFilter.value.trim().toLowerCase();
|
||||
const items = state.model.instances.filter((i) => i.ref.toLowerCase().includes(q));
|
||||
|
||||
el.instanceList.innerHTML = items
|
||||
.map((inst) => {
|
||||
renderVirtualList(
|
||||
el.instanceList,
|
||||
items,
|
||||
(inst) => {
|
||||
const cls = state.selectedRefs.includes(inst.ref) ? "active" : "";
|
||||
return `<li class="${cls}" data-ref-item="${inst.ref}">${inst.ref} · ${inst.symbol}</li>`;
|
||||
})
|
||||
.join("");
|
||||
},
|
||||
LIST_ROW_HEIGHT
|
||||
);
|
||||
}
|
||||
|
||||
function renderNets() {
|
||||
@ -747,12 +772,15 @@ function renderNets() {
|
||||
const q = el.netFilter.value.trim().toLowerCase();
|
||||
const items = state.model.nets.filter((n) => n.name.toLowerCase().includes(q));
|
||||
|
||||
el.netList.innerHTML = items
|
||||
.map((net) => {
|
||||
renderVirtualList(
|
||||
el.netList,
|
||||
items,
|
||||
(net) => {
|
||||
const cls = net.name === state.selectedNet ? "active" : "";
|
||||
return `<li class="${cls}" data-net-item="${net.name}">${net.name} <small>(${net.class})</small></li>`;
|
||||
})
|
||||
.join("");
|
||||
},
|
||||
LIST_ROW_HEIGHT
|
||||
);
|
||||
}
|
||||
|
||||
function netByName(name) {
|
||||
@ -1843,8 +1871,16 @@ async function loadSample() {
|
||||
}
|
||||
|
||||
function setupEvents() {
|
||||
el.instanceFilter.addEventListener("input", renderInstances);
|
||||
el.netFilter.addEventListener("input", renderNets);
|
||||
el.instanceFilter.addEventListener("input", () => {
|
||||
el.instanceList.scrollTop = 0;
|
||||
renderInstances();
|
||||
});
|
||||
el.netFilter.addEventListener("input", () => {
|
||||
el.netList.scrollTop = 0;
|
||||
renderNets();
|
||||
});
|
||||
el.instanceList.addEventListener("scroll", renderInstances, { passive: true });
|
||||
el.netList.addEventListener("scroll", renderNets, { passive: true });
|
||||
|
||||
el.instanceList.addEventListener("click", (evt) => {
|
||||
const item = evt.target.closest("[data-ref-item]");
|
||||
|
||||
@ -182,6 +182,13 @@ textarea {
|
||||
background: var(--accent-soft);
|
||||
}
|
||||
|
||||
.list li.listSpacer {
|
||||
padding: 0;
|
||||
border: none;
|
||||
cursor: default;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.card {
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user