Redesign toolbar sections to use horizontal button rows instead of vertical stacking. Fix component placement by attaching click handlers directly to dynamically created buttons and passing correct gate object shape to getComponentWidth/Height. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
135 lines
6.0 KiB
HTML
135 lines
6.0 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Logic Gates — MontLab</title>
|
|
<link rel="stylesheet" href="css/style.css">
|
|
</head>
|
|
<body>
|
|
<div id="toolbar">
|
|
<span class="logo">⚡ Logic Lab</span>
|
|
|
|
<!-- I/O Section -->
|
|
<div class="toolbar-section">
|
|
<div class="section-label">I/O</div>
|
|
<div class="section-buttons">
|
|
<button class="gate-btn input-btn" data-gate="INPUT">INPUT</button>
|
|
<button class="gate-btn clock-btn" data-gate="CLOCK">CLOCK</button>
|
|
<button class="gate-btn output-btn" data-gate="OUTPUT">OUTPUT</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="separator"></div>
|
|
|
|
<!-- Gates Section -->
|
|
<div class="toolbar-section">
|
|
<div class="section-label">Gates</div>
|
|
<div class="section-buttons">
|
|
<button class="gate-btn" data-gate="AND">AND</button>
|
|
<button class="gate-btn" data-gate="OR">OR</button>
|
|
<button class="gate-btn" data-gate="NOT">NOT</button>
|
|
<button class="gate-btn" data-gate="NAND">NAND</button>
|
|
<button class="gate-btn" data-gate="NOR">NOR</button>
|
|
<button class="gate-btn" data-gate="XOR">XOR</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="separator"></div>
|
|
|
|
<!-- Components Section -->
|
|
<div class="toolbar-section" id="components-section">
|
|
<div class="section-label">Components</div>
|
|
<div class="section-buttons">
|
|
<button class="create-component-btn" id="create-component-btn" title="Create custom component">✚ Create</button>
|
|
<div id="saved-components"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="separator"></div>
|
|
|
|
<button class="action-btn sim-btn" id="sim-btn">Waveform</button>
|
|
<div class="toolbar-right">
|
|
<button class="action-btn export-btn" id="export-btn" title="Export circuit">↓ Export</button>
|
|
<button class="action-btn import-btn" id="import-btn" title="Import circuit">↑ Import</button>
|
|
<button class="action-btn help-btn" id="help-btn">? Help</button>
|
|
<button class="action-btn" id="clear-btn">Clear All</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Hidden file input for import -->
|
|
<input type="file" id="import-file" accept=".json" style="display:none">
|
|
|
|
<!-- Component Editor Overlay -->
|
|
<div id="component-editor-overlay" style="display:none;">
|
|
<div id="component-editor-bar">
|
|
<span id="component-editor-title">Editing Component: </span>
|
|
<button id="component-editor-save">Save</button>
|
|
<button id="component-editor-cancel">Cancel</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Mode toggle will be inserted here by puzzleUI.js -->
|
|
|
|
<canvas id="canvas"></canvas>
|
|
|
|
<div id="waveform-panel">
|
|
<div id="wave-resize"></div>
|
|
<div id="wave-toolbar">
|
|
<span class="wave-title">Waveform Viewer</span>
|
|
<button class="wave-btn record active" id="wave-record">Record</button>
|
|
<button class="wave-btn" id="wave-clear">Clear</button>
|
|
<button class="wave-btn" id="wave-step">Step</button>
|
|
<button class="wave-btn" id="wave-zoom-out">Zoom -</button>
|
|
<span class="wave-info" id="wave-zoom-label" style="margin-left:0;min-width:35px;text-align:center">20px</span>
|
|
<button class="wave-btn" id="wave-zoom-in">Zoom +</button>
|
|
<div class="separator"></div>
|
|
<button class="wave-btn" id="sim-run-btn">Run</button>
|
|
<button class="wave-btn" id="sim-slower">-</button>
|
|
<span class="wave-info" id="sim-speed-label" style="margin-left:0">500ms</span>
|
|
<button class="wave-btn" id="sim-faster">+</button>
|
|
<span class="wave-info" id="wave-info">T=0 | 0 samples</span>
|
|
</div>
|
|
<div id="wave-container">
|
|
<div id="wave-labels"></div>
|
|
<canvas id="wave-canvas"></canvas>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="help-modal">
|
|
<div id="help-content">
|
|
<h2>Logic Gate Simulator</h2>
|
|
<ul>
|
|
<li>Click a gate button, then click on the canvas to place it</li>
|
|
<li>Drag gates to move them around</li>
|
|
<li>Click on an <strong>output port</strong> (right), then an <strong>input port</strong> (left) to connect</li>
|
|
<li>Click an <kbd>INPUT</kbd> gate to toggle its value (0/1)</li>
|
|
<li><kbd>Delete</kbd> while hovering a gate to remove it</li>
|
|
<li>Right-click a port to delete its connections</li>
|
|
<li><kbd>Escape</kbd> to cancel placing/connecting</li>
|
|
</ul>
|
|
<h3>Clock & Simulation</h3>
|
|
<ul>
|
|
<li>Place a <kbd>CLOCK</kbd> gate — it auto-toggles 0/1 during simulation</li>
|
|
<li>Click <kbd>Run</kbd> in the waveform bar to start the clock</li>
|
|
<li>Use <kbd>-</kbd> / <kbd>+</kbd> to adjust speed (50ms-2000ms per tick)</li>
|
|
<li>Connect CLOCK to gates to see automatic signal propagation</li>
|
|
</ul>
|
|
<h3>Waveform Viewer (GTKWave-style)</h3>
|
|
<ul>
|
|
<li>Click <kbd>Waveform</kbd> to toggle the signal viewer</li>
|
|
<li><kbd>Record</kbd> captures signal changes automatically</li>
|
|
<li><kbd>Step</kbd> manually advances one time step</li>
|
|
<li>Toggle inputs to see signals change in real-time</li>
|
|
<li>Drag the top border to resize the panel</li>
|
|
<li>All CLOCK, INPUT, OUTPUT, and gate signals are tracked</li>
|
|
</ul>
|
|
<p style="margin-top: 12px; color: #666;">Built at MontLab</p>
|
|
<button id="help-close">Got it</button>
|
|
</div>
|
|
</div>
|
|
|
|
<script type="module" src="js/app.js"></script>
|
|
</body>
|
|
</html>
|