|
| 1 | +<!DOCTYPE html> |
| 2 | +<html lang="en"> |
| 3 | +<head> |
| 4 | + <meta charset="utf-8"> |
| 5 | + <script>try{if(localStorage.getItem('pydevices-theme')==='light'){document.documentElement.setAttribute('data-theme','light');}}catch(e){}</script> |
| 6 | + <meta name="viewport" content="width=device-width, initial-scale=1"> |
| 7 | + <title>PyDevices Simulator — Live Python GUI & Embedded Playground</title> |
| 8 | + <meta name="description" content="Interactive browser-based Python playground for LVGL v9, pdwidgets, pygraphics, and displaydev on MicroPython and Pyodide."> |
| 9 | + <link rel="icon" type="image/svg+xml" href="https://pydevices.github.io/img/logo.svg"> |
| 10 | + <link rel="preconnect" href="https://fonts.googleapis.com"> |
| 11 | + <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> |
| 12 | + <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Space+Grotesk:wght@500;600;700&display=swap"> |
| 13 | + <link rel="stylesheet" href="./simulator.css"> |
| 14 | + <!-- LZ-String for compressed URL snippet sharing --> |
| 15 | + <script src="https://cdnjs.cloudflare.com/ajax/libs/lz-string/1.4.4/lz-string.min.js"></script> |
| 16 | + <!-- Monaco Editor AMD Loader --> |
| 17 | + <script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.45.0/min/vs/loader.js"></script> |
| 18 | +</head> |
| 19 | +<body> |
| 20 | + <!-- Top Action & Navigation Header --> |
| 21 | + <header class="sim-header"> |
| 22 | + <div class="sim-header-left"> |
| 23 | + <a href="https://pydevices.github.io/" class="sim-brand" title="PyDevices Home"> |
| 24 | + <img src="https://pydevices.github.io/img/logo.svg" alt="PyDevices Logo" width="28" height="28"> |
| 25 | + <span>PyDevices</span> |
| 26 | + </a> |
| 27 | + <span class="sim-badge">Simulator</span> |
| 28 | + </div> |
| 29 | + |
| 30 | + <div class="sim-header-center"> |
| 31 | + <!-- Preset Template Selector --> |
| 32 | + <div class="sim-select-wrap"> |
| 33 | + <select id="template-select" aria-label="Select Code Template"> |
| 34 | + <optgroup label="LVGL v9"> |
| 35 | + <option value="lvgl-counter" selected>LVGL v9: Interactive Counter</option> |
| 36 | + <option value="lvgl-thermostat">LVGL v9: Smart Thermostat Arc</option> |
| 37 | + </optgroup> |
| 38 | + <optgroup label="pdwidgets"> |
| 39 | + <option value="pdwidgets-dashboard">pdwidgets: Sensor Deck Dashboard</option> |
| 40 | + </optgroup> |
| 41 | + <optgroup label="pygraphics"> |
| 42 | + <option value="pygraphics-shapes">pygraphics: Vector & FrameBuffer Art</option> |
| 43 | + </optgroup> |
| 44 | + <optgroup label="displaydev"> |
| 45 | + <option value="displaydev-raw">displaydev: Direct Pixel Painter</option> |
| 46 | + </optgroup> |
| 47 | + </select> |
| 48 | + </div> |
| 49 | + |
| 50 | + <!-- Resolution & Shape Selector --> |
| 51 | + <div class="sim-select-wrap"> |
| 52 | + <select id="resolution-select" aria-label="Select Screen Resolution"> |
| 53 | + <option value="320x240" selected>320 × 240 (QVGA Landscape)</option> |
| 54 | + <option value="240x320">240 × 320 (QVGA Portrait)</option> |
| 55 | + <option value="240x240-square">240 × 240 (Square Watch)</option> |
| 56 | + <option value="240x240-round">240 × 240 (Round Watch)</option> |
| 57 | + <option value="480x320">480 × 320 (HVGA Landscape)</option> |
| 58 | + <option value="320x480">320 × 480 (HVGA Portrait)</option> |
| 59 | + <option value="800x480">800 × 480 (WVGA Landscape)</option> |
| 60 | + <option value="custom">Custom...</option> |
| 61 | + </select> |
| 62 | + </div> |
| 63 | + |
| 64 | + <!-- Runtime Engine Selector --> |
| 65 | + <div class="sim-select-wrap"> |
| 66 | + <select id="runtime-select" aria-label="Select Execution Runtime"> |
| 67 | + <option value="pyodide" selected>Pyodide (CPython 3.12)</option> |
| 68 | + <option value="mpy">MicroPython WASM</option> |
| 69 | + </select> |
| 70 | + </div> |
| 71 | + </div> |
| 72 | + |
| 73 | + <div class="sim-header-right"> |
| 74 | + <!-- Run / Restart Button --> |
| 75 | + <button type="button" class="sim-btn sim-btn-primary" id="run-btn" title="Run Script (Ctrl+Enter)"> |
| 76 | + <svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor"><polygon points="5 3 19 12 5 21 5 3"/></svg> |
| 77 | + <span>Run</span> |
| 78 | + <kbd>Ctrl+↵</kbd> |
| 79 | + </button> |
| 80 | + |
| 81 | + <!-- Share URL Button --> |
| 82 | + <button type="button" class="sim-btn" id="share-btn" title="Share Interactive Code Link"> |
| 83 | + <svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><line x1="8.59" y1="13.51" x2="15.42" y2="17.49"/><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"/></svg> |
| 84 | + <span>Share</span> |
| 85 | + </button> |
| 86 | + |
| 87 | + <!-- Theme Toggle --> |
| 88 | + <button type="button" class="sim-btn sim-icon-btn" id="theme-toggle" aria-label="Toggle Color Theme" title="Toggle Light/Dark Theme"> |
| 89 | + <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"/></svg> |
| 90 | + </button> |
| 91 | + </div> |
| 92 | + </header> |
| 93 | + |
| 94 | + <!-- Main Resizable Workspace --> |
| 95 | + <main class="sim-workspace" id="workspace"> |
| 96 | + <!-- Left Pane: Monaco Code Editor --> |
| 97 | + <section class="sim-editor-pane" id="editor-pane" aria-label="Code Editor"> |
| 98 | + <div class="sim-pane-header"> |
| 99 | + <div class="sim-tab"> |
| 100 | + <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg> |
| 101 | + <span>main.py</span> |
| 102 | + </div> |
| 103 | + <div class="sim-status-indicator"> |
| 104 | + <span class="sim-status-dot is-ready" id="status-dot"></span> |
| 105 | + <span id="status-text">Ready</span> |
| 106 | + </div> |
| 107 | + </div> |
| 108 | + <div class="sim-editor-container" id="editor-container"></div> |
| 109 | + </section> |
| 110 | + |
| 111 | + <!-- Vertical Drag Splitter --> |
| 112 | + <div class="sim-splitter" id="splitter-v" role="separator" aria-orientation="vertical"></div> |
| 113 | + |
| 114 | + <!-- Right Pane: Simulator & Console --> |
| 115 | + <section class="sim-preview-pane" id="preview-pane" aria-label="Simulator and Console Output"> |
| 116 | + <!-- Top Sub-Pane: Hardware Canvas Bezel Stage --> |
| 117 | + <div class="sim-device-stage" id="device-stage"> |
| 118 | + <div class="sim-device-bezel" id="device-bezel"> |
| 119 | + <canvas id="display_canvas" width="320" height="240" tabindex="0"></canvas> |
| 120 | + <canvas id="aux_canvas" width="1" height="1" tabindex="0"></canvas> |
| 121 | + </div> |
| 122 | + </div> |
| 123 | + |
| 124 | + <!-- Horizontal Drag Splitter --> |
| 125 | + <div class="sim-splitter-h" id="splitter-h" role="separator" aria-orientation="horizontal"></div> |
| 126 | + |
| 127 | + <!-- Bottom Sub-Pane: Console / REPL Stream --> |
| 128 | + <section class="sim-console-pane" id="console-pane" aria-label="Console Output"> |
| 129 | + <div class="sim-pane-header"> |
| 130 | + <div class="sim-tab"> |
| 131 | + <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 17 10 11 4 5"/><line x1="12" y1="19" x2="20" y2="19"/></svg> |
| 132 | + <span>Console Output</span> |
| 133 | + </div> |
| 134 | + <button type="button" class="sim-btn sim-icon-btn" id="clear-console-btn" title="Clear Console"> |
| 135 | + <svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg> |
| 136 | + </button> |
| 137 | + </div> |
| 138 | + <div class="sim-console-body" id="console-log"></div> |
| 139 | + </section> |
| 140 | + </section> |
| 141 | + </main> |
| 142 | + |
| 143 | + <!-- Toast Notification --> |
| 144 | + <div class="sim-toast" id="sim-toast">✓ Link copied to clipboard!</div> |
| 145 | + |
| 146 | + <!-- Simulator Application Scripts --> |
| 147 | + <script src="./templates.js"></script> |
| 148 | + <script src="./simulator.js"></script> |
| 149 | +</body> |
| 150 | +</html> |
0 commit comments