From 607cfe3b9f90e9895230022dcfe1ed62581839d0 Mon Sep 17 00:00:00 2001 From: Ross Andrews Date: Fri, 3 May 2024 21:08:14 -0500 Subject: [PATCH] Changed layout, three-column --- vweb/src/forge_simulator.jsx | 87 ++++++++++++++++++++++++++++-------- vweb/src/simulator.css | 49 +++++++------------- 2 files changed, 86 insertions(+), 50 deletions(-) diff --git a/vweb/src/forge_simulator.jsx b/vweb/src/forge_simulator.jsx index 306d990..3afb986 100644 --- a/vweb/src/forge_simulator.jsx +++ b/vweb/src/forge_simulator.jsx @@ -1,4 +1,4 @@ -import React, { useState, useCallback, useRef } from 'react' +import React, {useState, useCallback, useRef, useEffect} from 'react' import ForgeEditor from "./forge_editor" import EmulatorDisplay from "./emulator_display" import { WasmCPU, assemble_snippet, compile_forge } from '../pkg/vweb.js' @@ -14,17 +14,42 @@ export default function({ src: defaultSrc }) { // Whether the emulator should be running. Has to be a ref because the CPU setTimeout loop won't ever see changes in it otherwise const running = useRef(false) + const [currentFile, setCurrentFile] = useState(() => (Object.keys(window.localStorage)[0] || 'example')) + useEffect(() => { + if (!currentFile) { + setCurrentFile('example') + window.localStorage.setItem('example', defaultSrc) + } + }, []) + + const selectFile = useCallback((name) => { + setSrc(window.localStorage.getItem(name)) + setCurrentFile(name) + }, []) + + const addFile = useCallback(() => { + const fileList = Object.keys(window.localStorage) + let name = null + while(!name || fileList.indexOf(name) >= 0) { + name = prompt('Create new file named:') + } + window.localStorage[name] = '' + selectFile(name) + }, []) + + const removeFile = useCallback((name) => {}, []) + // The current Forge source. Our initial state tries to look something up from localStorage, // then if that fails uses the prop. const [src, setSrc] = useState(() => { - return window.localStorage.getItem('src') || undent(defaultSrc) + return window.localStorage.getItem(currentFile) || undent(defaultSrc) }) // When we update the src, also update the key in localStorage const updateSrc = useCallback((newSrc) => { setSrc(newSrc) - window.localStorage.setItem('src', newSrc) - }, []) + window.localStorage.setItem(currentFile, newSrc) + }, [currentFile]) // Callback for the build button const build = useCallback(() => { @@ -71,21 +96,42 @@ export default function({ src: defaultSrc }) { setStatus('Stopped by user') }, []) + let content; + if (activeTab === 'assembly') { + content =
{assembly}
+ } else if (activeTab === 'errors') { + content =
{errors}
+ } else if (activeTab === 'editor') { + content = + } + return ( <> - -
- {activeTab === 'editor' && } - {activeTab === 'assembly' &&
{assembly}
} - {activeTab === 'display' && } - {activeTab === 'errors' &&
{errors}
} -
+ + +
{content}
+ ) } +// A list of "files" stored in localStorage, that we can display / build / compile +function FileList({ fileList, selectFile }) { + const clickFile = useCallback((event) => { + const name = event.target.getAttribute('data-name') + selectFile(name) + event.preventDefault() + }, [selectFile]) + const fileRows = fileList.map(file =>
{file}
) + return ( +
+ {fileRows} +
+ ) +} + // A tabbar of the various pages in the simulator function Tabbar({ activeTab, setActiveTab, anyErrors }) { let onChangeTab = useCallback((event) => { @@ -97,7 +143,6 @@ function Tabbar({ activeTab, setActiveTab, anyErrors }) { return ( @@ -105,7 +150,7 @@ function Tabbar({ activeTab, setActiveTab, anyErrors }) { } // Toolbar of the controls for the simulator -function Toolbar({ activeTab, running, compile, build, run, stop }) { +function Toolbar({activeTab, running, compile, build, run, stop, addFile, removeFile }) { let buildBtn, runBtn // TODO: Make this assemble on assembly tab, make that editable buildBtn = [Build] @@ -117,14 +162,20 @@ function Toolbar({ activeTab, running, compile, build, run, stop }) { } return ( -
- {buildBtn} - {runBtn} -
+ <> +
+ [new] + [del] +
+
+ {buildBtn} + {runBtn} +
+ ) } // The short status line at the bottom -function Status({ message }) { +function Status({message}) { return
{message}
} \ No newline at end of file diff --git a/vweb/src/simulator.css b/vweb/src/simulator.css index 4b9b086..b8f5b34 100644 --- a/vweb/src/simulator.css +++ b/vweb/src/simulator.css @@ -10,18 +10,19 @@ a { color: #cccccc; } .simulator { display: grid; grid-template: - "tab" 1em - "btns" 1em - "content" 1fr - "status" 1em / 1fr; + "filebtns tab btns" 1em + "files content screen " 1fr + "files status screen" 1em / 16em 1fr calc(640px + 3em); row-gap: 0.3em; } /* Setting where things go in the grid */ .tabbar { grid-area: tab } .buttons { grid-area: btns } +.file-buttons { grid-area: filebtns } .content { grid-area: content } .status { grid-area: status } +.files { grid-area: files } /* Make the content fill the remainder of the screen */ .content { @@ -40,48 +41,32 @@ a { color: #cccccc; } height: calc(100vh - 5em) } -/*!* Make the textarea look presentable (TODO: replace with CodeMirror) *!*/ -/*.content textarea {*/ -/* height: 100%;*/ -/* width: 100%;*/ -/* padding: 0;*/ -/* margin: 0;*/ -/* background: #000000;*/ -/* color: #a0a0a0;*/ -/* border: none;*/ -/* resize: none;*/ -/* outline: none;*/ -/*}*/ - -/*.forge-editor textarea:focus {*/ -/* border: none;*/ -/* outline: none;*/ -/*}*/ - /* Status, btns, tabs all look right */ -.status, .buttons, .tabbar { font-weight: bold; } -.tabbar a, .buttons a { cursor: pointer; } +.status, .buttons, .file-buttons, .tabbar { font-weight: bold; } +.tabbar a, .buttons a, .file-buttons a, .file { cursor: pointer; } -/* Make the display the right size by centering the canvas in a rectangle*/ +/* Make the display the right size by centering the canvas in a rectangle */ +/* The display is in the screen section of the main grid but it's also got to define its own grid */ .display { + grid-area: screen; height: 100%; display: grid; grid-template: "lt top rt" 1fr - "lt screen rt" calc(480px + 4em) - "lt btm rt" 1fr / 1fr calc(640px + 4em) 1fr; + "lt screen rt" calc(480px + 2em) + "lt btm rt" 1fr / 1fr calc(640px + 2em) 1fr; } /* The beige monitor border around the screen */ .display { background-color: #0f0f0f } .display canvas { grid-area: screen; - border: 2em solid #bb9; - border-radius: 2em; + border: 1em solid #bb9; + border-radius: 1em; } /* Colors of tabs and buttons */ .tabbar a.active { background-color: #686868; } -.buttons .run { color: #66bb66 } -.buttons .stop { color: #bb6666 } -.buttons .build { color: #aaaaff; } \ No newline at end of file +.buttons .run, .file-buttons .new { color: #66bb66 } +.buttons .stop, .file-buttons .del { color: #bb6666 } +.buttons .build { color: #aaaaff; }