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}
-
+ <>
+
+
+ {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; }