feat: remove code output footer, move actions to top bar, download .ll
- Remove global-toolbar (footer with code display) entirely - Move Generate, Save, Load, New, Tests buttons to algorithm pane toolbar - Replace prog.generateCode() with prog.generateAndDownload() — creates a Blob from the IR and triggers a program.ll download via a temp <a> - Remove copyCode function from helpers.js (no longer needed) - Remove global-toolbar and .code-output CSS rules - Add .action-btn styling for the text buttons in pane-toolbar
This commit is contained in:
@@ -230,9 +230,17 @@ function setupUI() {
|
||||
const btn = e.target.closest("button");
|
||||
if (!btn) return;
|
||||
if (handleBlockAction(btn)) return;
|
||||
const prog = $id("main-program");
|
||||
if (btn.dataset.action === "add-section" && typeof enterSectionCreateMode === "function") {
|
||||
enterSectionCreateMode();
|
||||
}
|
||||
if (btn.dataset.action === "generate") prog.generateAndDownload();
|
||||
if (btn.dataset.action === "save") saveWorkspace();
|
||||
if (btn.dataset.action === "load") loadWorkspace();
|
||||
if (btn.dataset.action === "new") newWorkspace();
|
||||
if (btn.dataset.action === "run-tests") {
|
||||
if (window.APP_TEST_SUITE) APP_TEST_SUITE.run();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -340,25 +348,6 @@ function setupUI() {
|
||||
});
|
||||
}
|
||||
|
||||
/* Global toolbar */
|
||||
const globalToolbar = document.querySelector(".global-toolbar");
|
||||
if (globalToolbar) {
|
||||
globalToolbar.addEventListener("click", e => {
|
||||
const btn = e.target.closest("button");
|
||||
if (!btn) return;
|
||||
const prog = $id("main-program");
|
||||
if (!prog) { showError("Main program element not found"); return; }
|
||||
if (btn.dataset.action === "generate") prog.generateCode();
|
||||
if (btn.dataset.action === "save") saveWorkspace();
|
||||
if (btn.dataset.action === "load") loadWorkspace();
|
||||
if (btn.dataset.action === "new") newWorkspace();
|
||||
if (btn.dataset.action === "copy-code") copyCode();
|
||||
if (btn.dataset.action === "run-tests") {
|
||||
if (window.APP_TEST_SUITE) APP_TEST_SUITE.run();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* Tab bar */
|
||||
const tabBar = document.querySelector(".tab-bar");
|
||||
if (tabBar) {
|
||||
|
||||
@@ -232,11 +232,6 @@ function findDataSource(hook) {
|
||||
}
|
||||
|
||||
/** Copies the generated C code text to the clipboard. */
|
||||
function copyCode() {
|
||||
const el = $id("ir-code");
|
||||
if (el && el.textContent) navigator.clipboard.writeText(el.textContent).catch(() => {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes special characters for embedding in a C string literal.
|
||||
* Handles backslash, double-quote, newline, carriage return, and tab.
|
||||
|
||||
+7
-12
@@ -374,6 +374,12 @@
|
||||
<button data-action="add-section" title="draw a logic section">
|
||||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" stroke="currentColor" stroke-width="2"><line x1="9" y1="3" x2="9" y2="15"/><line x1="3" y1="9" x2="15" y2="9"/></svg>
|
||||
</button>
|
||||
<span class="toolbar-sep"></span>
|
||||
<button data-action="generate" class="action-btn">Generate</button>
|
||||
<button data-action="save" class="action-btn">Save</button>
|
||||
<button data-action="load" class="action-btn">Load</button>
|
||||
<button data-action="new" class="action-btn">New</button>
|
||||
<button data-action="run-tests" class="action-btn">Tests</button>
|
||||
</div>
|
||||
<div id="draw-area">
|
||||
<svg id="connections" xmlns="http://www.w3.org/2000/svg">
|
||||
@@ -438,18 +444,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bottom toolbar: code generation button and highlighted output. -->
|
||||
<div class="global-toolbar">
|
||||
<button data-action="generate">Generate code</button>
|
||||
<button data-action="save">Save</button>
|
||||
<button data-action="load">Load</button>
|
||||
<button data-action="new">New</button>
|
||||
<button data-action="copy-code">Copy</button>
|
||||
<button data-action="run-tests">Tests</button>
|
||||
<div class="code-output" id="ir-code-container">
|
||||
<pre><code id="ir-code"></code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Empty placeholder removed; actions moved to algorithm pane toolbar. -->
|
||||
<div id="error-overlay" class="error-overlay">
|
||||
<div class="error-box">
|
||||
<span class="error-close">×</span>
|
||||
|
||||
@@ -46,6 +46,12 @@ h1 {
|
||||
flex-shrink: 0; flex-wrap: wrap;
|
||||
background: var(--surface); border-bottom: 1px solid var(--border);
|
||||
}
|
||||
.pane-toolbar button.action-btn {
|
||||
padding: 0.3rem 0.6rem; font-size: 0.78rem; font-weight: 500;
|
||||
background: var(--accent); color: #fff; border: 1px solid var(--accent);
|
||||
line-height: 1.2;
|
||||
}
|
||||
.pane-toolbar button.action-btn:hover { background: #357abd; border-color: #357abd; }
|
||||
.pane-toolbar button {
|
||||
padding: 0.3rem; font: inherit; font-size: 0.75rem; cursor: pointer;
|
||||
background: var(--bg); color: var(--text); border: 1px solid var(--border);
|
||||
@@ -463,31 +469,7 @@ wc-assign #hook-next[data-direction="out"] {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.global-toolbar {
|
||||
display: flex; gap: 0.25rem; padding: 0.3rem;
|
||||
align-items: flex-start; flex-shrink: 0;
|
||||
border-top: 1px solid var(--border); background: var(--surface);
|
||||
}
|
||||
.global-toolbar button {
|
||||
padding: 0.4rem 0.8rem; font: inherit; font-size: 0.8rem; cursor: pointer;
|
||||
background: var(--accent); color: #fff; border: none; border-radius: 3px;
|
||||
}
|
||||
.global-toolbar button:hover { background: #357abd; }
|
||||
.global-toolbar .code-output {
|
||||
flex: 1; min-height: 80px; max-height: 50vh; overflow: auto; resize: vertical;
|
||||
background: var(--bg); border: 1px solid var(--border);
|
||||
font-family: 'Courier New', monospace; font-size: 0.8rem; line-height: 1.5;
|
||||
padding: 0.3rem; position: relative;
|
||||
}
|
||||
.global-toolbar .code-output pre {
|
||||
margin: 0; white-space: pre; tab-size: 4;
|
||||
}
|
||||
.global-toolbar .code-output code {
|
||||
display: block;
|
||||
}
|
||||
.global-toolbar .code-output code.hljs {
|
||||
background: transparent; padding: 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
[data-block] {
|
||||
|
||||
+16
-12
@@ -208,12 +208,8 @@ class WCProgram extends HTMLElement {
|
||||
return lines.join("\n");
|
||||
}
|
||||
|
||||
generateCode() {
|
||||
const outputEl = $id("ir-code");
|
||||
if (!outputEl) { showError("Missing #ir-code output element"); return; }
|
||||
|
||||
_generateIR() {
|
||||
const { usedQuantities, usedUnits } = this._gatherUsedTypes();
|
||||
|
||||
const typeDefs = this._generateTypeDefs(usedQuantities);
|
||||
const unitDefs = this._generateUnitDefs(usedUnits);
|
||||
const { boolDefs, scalarDefs, vectorDefs, stringDefs, arrayDefs } = this._generateVariableDeclarations();
|
||||
@@ -225,24 +221,32 @@ class WCProgram extends HTMLElement {
|
||||
? CodeGen.emitFlat(firstChild)
|
||||
: "; no flowchart body\n";
|
||||
|
||||
// Collect external function declarations from used libraries
|
||||
const proccalls = this.querySelectorAll("wc-proccall");
|
||||
const decls = this._generateLLVMDecls(proccalls);
|
||||
|
||||
// Collect string globals
|
||||
const strPool = CodeGen.getStringPool();
|
||||
const globals = strPool.map(function (_, i) { return CodeGen.stringGlobal(i); }).join("\n");
|
||||
|
||||
// Variable declarations -> alloca instructions in the prologue
|
||||
const dataSection = (boolDefs || scalarDefs || vectorDefs || stringDefs || arrayDefs)
|
||||
? [boolDefs, scalarDefs, vectorDefs, stringDefs, arrayDefs]
|
||||
.filter(Boolean).map(function (s) { return s + "\n"; }).join("")
|
||||
: "";
|
||||
|
||||
const raw = CodeGen.generateIRFile(firstChild, decls, globals, dataSection);
|
||||
outputEl.textContent = raw;
|
||||
if (typeof hljs !== "undefined") hljs.highlightElement(outputEl);
|
||||
outputEl.parentElement.dataset.language = "llvm";
|
||||
return CodeGen.generateIRFile(firstChild, decls, globals, dataSection);
|
||||
}
|
||||
|
||||
generateAndDownload() {
|
||||
const ir = this._generateIR();
|
||||
if (!ir) { showError("No IR to download"); return; }
|
||||
const blob = new Blob([ir], { type: "text/plain" });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement("a");
|
||||
a.href = url;
|
||||
a.download = "program.ll";
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user