From 4f9ec93d7065c1776e0eca1aef842706d5930d0d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=A3o=20Magalh=C3=A3es?= <joamag@gmail.com>
Date: Sat, 22 Oct 2022 17:20:33 +0100
Subject: [PATCH] feat: initial display support

---
 examples/web/react/app.tsx                    | 11 ++-
 .../web/react/components/display/display.css  | 71 +++++++++++++++++++
 .../web/react/components/display/display.tsx  | 54 ++++++++++++++
 .../web/react/components/display/minimise.svg |  1 +
 examples/web/react/components/index.ts        |  1 +
 5 files changed, 137 insertions(+), 1 deletion(-)
 create mode 100644 examples/web/react/components/display/display.css
 create mode 100644 examples/web/react/components/display/display.tsx
 create mode 100644 examples/web/react/components/display/minimise.svg

diff --git a/examples/web/react/app.tsx b/examples/web/react/app.tsx
index 3144dab2..7cfc6986 100644
--- a/examples/web/react/app.tsx
+++ b/examples/web/react/app.tsx
@@ -1,11 +1,14 @@
 import React, { FC, useEffect, useState } from "react";
 import ReactDOM from "react-dom/client";
 
+declare const require: any;
+
 import {
     Button,
     ButtonContainer,
     ButtonIncrement,
     ButtonSwitch,
+    Display,
     Footer,
     Info,
     Link,
@@ -61,7 +64,13 @@ export const App: FC<AppProps> = ({ emulator, backgrounds = ["264653"] }) => {
                     João Magalhães
                 </Link>
             </Footer>
-            <PanelSplit left={<div>This is the left panel</div>}>
+            <PanelSplit
+                left={
+                    <div>
+                        <Display />
+                    </div>
+                }
+            >
                 <Title
                     text={emulator.getName()}
                     version={emulator.getVersion()}
diff --git a/examples/web/react/components/display/display.css b/examples/web/react/components/display/display.css
new file mode 100644
index 00000000..f2337ed6
--- /dev/null
+++ b/examples/web/react/components/display/display.css
@@ -0,0 +1,71 @@
+.display {
+    max-width: 100%;
+}
+
+.display.fullscreen {
+    align-items: center;
+    background-color: #2d2d2d;
+    display: flex;
+    height: 100%;
+    justify-content: center;
+    left: 0px;
+    position: fixed;
+    top: 0px;
+    width: 100%;
+    z-index: 6;
+}
+
+.display > .display-close {
+    bottom: 22px;
+    display: none;
+    position: absolute;
+    right: 22px;
+    user-select: none;
+    -o-user-select: none;
+    -ms-user-select: none;
+    -moz-user-select: none;
+    -khtml-user-select: none;
+    -webkit-user-select: none;
+}
+
+.display > .display-close > img {
+    height: 32px;
+    width: 32px;
+}
+
+.display.fullscreen > .display-close {
+    display: block;
+}
+
+.display > .display-frame {
+    background-color: #1b1a17;
+    border: 2px solid #50cb93;
+    font-size: 0px;
+    margin-top: 78px;
+    max-width: 320px;
+    padding: 8px 8px 8px 8px;
+}
+
+@media only screen and (max-width: 1120px) {
+    .display > .display-frame {
+        margin-top: 12px;
+    }
+}
+
+.display.fullscreen > .display-frame {
+    background-color: transparent;
+    border: none;
+    box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.24);
+    -o-box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.24);
+    -ms-box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.24);
+    -moz-box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.24);
+    -khtml-box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.24);
+    -webkit-box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.24);
+    margin: 0px 0px 0px 0px;
+    max-width: unset;
+    padding: 0px 0px 0px 0px;
+}
+
+.display > .display-frame > .display-canvas {
+    width: 100%;
+}
diff --git a/examples/web/react/components/display/display.tsx b/examples/web/react/components/display/display.tsx
new file mode 100644
index 00000000..116307f8
--- /dev/null
+++ b/examples/web/react/components/display/display.tsx
@@ -0,0 +1,54 @@
+import React, { FC, useState } from "react";
+
+import "./display.css";
+
+declare const require: any;
+
+type DisplayOptions = {
+    width: number;
+    height: number;
+    scale?: number;
+};
+
+type DisplayProps = {
+    options?: DisplayOptions;
+    size?: string;
+    style?: string[];
+};
+
+export const Display: FC<DisplayProps> = ({
+    options = {},
+    size = "small",
+    style = []
+}) => {
+    const classes = () => ["display", size, ...style].join(" ");
+    options = { ...options, ...{ width: 320, height: 288 } };
+    if (!options.scale) {
+        options.scale = window.devicePixelRatio ? window.devicePixelRatio : 1;
+    }
+    return (
+        <div id="display" className={classes()}>
+            <span id="display-close" className="magnify-button canvas-close">
+                <img
+                    className="large"
+                    src={require("./minimise.svg")}
+                    alt="minimise"
+                />
+            </span>
+            <div className="display-frame">
+                <canvas
+                    id="display-canvas"
+                    className="canvas"
+                    width={options.width * options.scale}
+                    height={options.height * options.scale}
+                    style={{
+                        width: `${options.width}px`,
+                        height: `${options.height}px`
+                    }}
+                ></canvas>
+            </div>
+        </div>
+    );
+};
+
+export default Display;
diff --git a/examples/web/react/components/display/minimise.svg b/examples/web/react/components/display/minimise.svg
new file mode 100644
index 00000000..3d41ee13
--- /dev/null
+++ b/examples/web/react/components/display/minimise.svg
@@ -0,0 +1 @@
+<svg role="img" xmlns="http://www.w3.org/2000/svg" width="48px" height="48px" viewBox="0 0 24 24" aria-labelledby="minimiseIconTitle" stroke="#ffffff" stroke-width="3" stroke-linecap="square" stroke-linejoin="miter" fill="none" color="#ffffff"> <title id="minimiseIconTitle">Minimise View</title> <polyline points="8 3 8 8 3 8"/> <polyline points="21 8 16 8 16 3"/> <polyline points="3 16 8 16 8 21"/> <polyline points="16 21 16 16 21 16"/> </svg>
\ No newline at end of file
diff --git a/examples/web/react/components/index.ts b/examples/web/react/components/index.ts
index 9f2a21f3..f6605b0e 100644
--- a/examples/web/react/components/index.ts
+++ b/examples/web/react/components/index.ts
@@ -2,6 +2,7 @@ export * from "./button/button";
 export * from "./button-container/button-container";
 export * from "./button-increment/button-increment";
 export * from "./button-switch/button-switch";
+export * from "./display/display";
 export * from "./footer/footer";
 export * from "./info/info";
 export * from "./link/link";
-- 
GitLab