From fde73f0702f9b5c58517202e7a749b21a694cd7f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=A3o=20Magalh=C3=A3es?= <joamag@gmail.com>
Date: Sat, 8 Oct 2022 19:33:34 +0100
Subject: [PATCH] feat: new abstract emulator logic and button container

---
 examples/web/index.ts                         |  9 ++--
 examples/web/react/app.tsx                    | 53 +++++++++++++------
 .../button-container/button-container.css     |  7 +++
 .../button-container/button-container.tsx     | 18 +++++++
 examples/web/react/components/index.ts        |  1 +
 5 files changed, 67 insertions(+), 21 deletions(-)
 create mode 100644 examples/web/react/components/button-container/button-container.css
 create mode 100644 examples/web/react/components/button-container/button-container.tsx

diff --git a/examples/web/index.ts b/examples/web/index.ts
index 7f88a378..e2799249 100644
--- a/examples/web/index.ts
+++ b/examples/web/index.ts
@@ -1,4 +1,4 @@
-import { startApp } from "./react/app";
+import { Emulator, startApp } from "./react/app";
 
 import { default as _wasm, GameBoy, PadKey, PpuMode } from "./lib/boytacean.js";
 import info from "./package.json";
@@ -55,7 +55,7 @@ enum PixelFormat {
  * and "joins" all the elements together to bring input/output
  * of the associated machine.
  */
-class Emulator {
+class GameboyEmulator implements Emulator {
     /**
      * The Game Boy engine (probably coming from WASM) that
      * is going to be used for the emulation.
@@ -1083,8 +1083,7 @@ const wasm = async () => {
 };
 
 (async () => {
-    startApp("app", BACKGROUNDS);
-
-    const emulator = new Emulator();
+    const emulator = new GameboyEmulator();
+    startApp("app", emulator, BACKGROUNDS);
     await emulator.main();
 })();
diff --git a/examples/web/react/app.tsx b/examples/web/react/app.tsx
index 11f5198d..39ba6f97 100644
--- a/examples/web/react/app.tsx
+++ b/examples/web/react/app.tsx
@@ -3,6 +3,7 @@ import ReactDOM from "react-dom/client";
 
 import {
     Button,
+    ButtonContainer,
     ButtonIncrement,
     ButtonSwitch,
     Footer,
@@ -17,11 +18,16 @@ import {
 
 import "./app.css";
 
+export interface Emulator {
+    reset(): void;
+}
+
 type AppProps = {
+    emulator: Emulator;
     backgrounds?: string[];
 };
 
-export const App: FC<AppProps> = ({ backgrounds = ["264653"] }) => {
+export const App: FC<AppProps> = ({ emulator, backgrounds = ["264653"] }) => {
     const [count, setCount] = useState(0);
     const [backgroundIndex, setBackgroundIndex] = useState(0);
     const getText = () => `Hello World ${count}`;
@@ -30,6 +36,9 @@ export const App: FC<AppProps> = ({ backgrounds = ["264653"] }) => {
     const onThemeClick = () => {
         setBackgroundIndex((backgroundIndex + 1) % backgrounds.length);
     };
+    const onResetClick = () => {
+        emulator.reset();
+    };
     useEffect(() => {
         document.body.style.backgroundColor = `#${getBackground()}`;
     });
@@ -83,19 +92,27 @@ export const App: FC<AppProps> = ({ backgrounds = ["264653"] }) => {
                     </Paragraph>
                 </Section>
                 <Section>
-                    <Button text={getText()} onClick={onClick} />
-                    <Button
-                        text={getText()}
-                        image={require("../res/pause.svg")}
-                        imageAlt="tobias"
-                        onClick={onClick}
-                    />
-                    <Button
-                        text={"Theme"}
-                        image={require("../res/marker.svg")}
-                        imageAlt="marker"
-                        onClick={onThemeClick}
-                    />
+                    <ButtonContainer>
+                        <Button text={getText()} onClick={onClick} />
+                        <Button
+                            text={getText()}
+                            image={require("../res/pause.svg")}
+                            imageAlt="tobias"
+                            onClick={onClick}
+                        />
+                        <Button
+                            text={"Reset"}
+                            image={require("../res/reset.svg")}
+                            imageAlt="reset"
+                            onClick={onResetClick}
+                        />
+                        <Button
+                            text={"Theme"}
+                            image={require("../res/marker.svg")}
+                            imageAlt="marker"
+                            onClick={onThemeClick}
+                        />
+                    </ButtonContainer>
                     <Info>
                         <Pair
                             key="tobias"
@@ -134,14 +151,18 @@ export const App: FC<AppProps> = ({ backgrounds = ["264653"] }) => {
     );
 };
 
-export const startApp = (element: string, backgrounds: string[]) => {
+export const startApp = (
+    element: string,
+    emulator: Emulator,
+    backgrounds: string[]
+) => {
     const elementRef = document.getElementById(element);
     if (!elementRef) {
         return;
     }
 
     const root = ReactDOM.createRoot(elementRef);
-    root.render(<App backgrounds={backgrounds} />);
+    root.render(<App emulator={emulator} backgrounds={backgrounds} />);
 };
 
 export default App;
diff --git a/examples/web/react/components/button-container/button-container.css b/examples/web/react/components/button-container/button-container.css
new file mode 100644
index 00000000..eb4dc7f3
--- /dev/null
+++ b/examples/web/react/components/button-container/button-container.css
@@ -0,0 +1,7 @@
+.button-container > * {
+    margin-right: 8px;
+}
+
+.button-container > *:last-child {
+    margin-right: 0px;
+}
diff --git a/examples/web/react/components/button-container/button-container.tsx b/examples/web/react/components/button-container/button-container.tsx
new file mode 100644
index 00000000..b11fc1f1
--- /dev/null
+++ b/examples/web/react/components/button-container/button-container.tsx
@@ -0,0 +1,18 @@
+import React, { FC, ReactNode } from "react";
+
+import "./button-container.css";
+
+type ButtonContainerProps = {
+    children: ReactNode;
+    style?: string[];
+};
+
+export const ButtonContainer: FC<ButtonContainerProps> = ({
+    children,
+    style = []
+}) => {
+    const classes = () => ["button-container", ...style].join(" ");
+    return <div className={classes()}>{children}</div>;
+};
+
+export default ButtonContainer;
diff --git a/examples/web/react/components/index.ts b/examples/web/react/components/index.ts
index b3c9a92d..9f2a21f3 100644
--- a/examples/web/react/components/index.ts
+++ b/examples/web/react/components/index.ts
@@ -1,4 +1,5 @@
 export * from "./button/button";
+export * from "./button-container/button-container";
 export * from "./button-increment/button-increment";
 export * from "./button-switch/button-switch";
 export * from "./footer/footer";
-- 
GitLab