From cda1b5c97269b4557fe4bb47a50a8e6b39a983de Mon Sep 17 00:00:00 2001 From: David Meincke Date: Thu, 24 Mar 2022 23:00:10 +0100 Subject: [PATCH] added theme and gradients and stuff --- codeeditor-app/app.html | 5 +- codeeditor-app/app.less | 27 ++++---- codeeditor-app/boot.ts | 2 + .../elements/code-editor/code-editor.less | 13 +++- .../elements/code-editor/code-editor.ts | 7 +- .../code-editor/injects/declarations.d.ts | 2 +- .../injects/spiral-boxes-solution.js | 6 +- .../notification-bubble.less | 4 +- .../elements/output-frame/output-frame.less | 7 +- .../elements/resize-handle/resize-handle.less | 24 +++++++ .../elements/resize-handle/resize-handle.ts | 65 +++++++++++++++++++ outputframe-app/app.less | 11 ++-- .../elements/render-canvas/render-canvas.less | 9 ++- .../elements/render-canvas/render-canvas.ts | 51 +++++++++++---- outputframe-app/injects/dom-helpers.ts | 9 ++- shared/less-theme-to-obj.ts | 17 +++++ shared/theme.less | 17 +++++ 17 files changed, 225 insertions(+), 51 deletions(-) create mode 100644 codeeditor-app/elements/resize-handle/resize-handle.less create mode 100644 codeeditor-app/elements/resize-handle/resize-handle.ts create mode 100644 shared/less-theme-to-obj.ts create mode 100644 shared/theme.less diff --git a/codeeditor-app/app.html b/codeeditor-app/app.html index 7fee2d9..e022ccc 100644 --- a/codeeditor-app/app.html +++ b/codeeditor-app/app.html @@ -4,7 +4,10 @@
- +
+ + +
methods: rect, box, center, width, height, rand
diff --git a/codeeditor-app/app.less b/codeeditor-app/app.less index 48ca5aa..af2d476 100644 --- a/codeeditor-app/app.less +++ b/codeeditor-app/app.less @@ -1,8 +1,11 @@ +@import url('../shared/theme.less'); + html, body { margin: 0; width: 100%; height: 100%; overflow: hidden; + background: @median-bg-white; } .flex-horiz { @@ -46,41 +49,41 @@ html, body { } body { - font-family: "Segoe UI", Frutiger, "Frutiger Linotype", "Dejavu Sans", "Helvetica Neue", Arial, sans-serif; + font-family: @primary-font-family; } .section { - background: #e3e3e3; - padding: 20px; - font-size: 22px; + background: @primary-bg-color-white; + padding: 10px; + font-size: 18px; } .section.top { - border-bottom: 1px solid #c2c2c2; + border-bottom: 1px solid @primary-border-color-white; } .section.bottom { padding: 10px; - border-top: 1px solid #c2c2c2; - font-size: 14px; + border-top: 1px solid @primary-border-color-white; + font-size: 10px; text-align: right; } @media (prefers-color-scheme: dark) { body { - background: #1e1e1e; + background: @median-bg-dark; } .section { - color: white; - background: #2e2e2e; + color: @primary-text-color-dark; + background: @primary-bg-color-dark; } .section.top { - border-color: #292929; + border-color: @primary-border-color-dark; } .section.bottom { - border-color: #292929; + border-color: @primary-bg-color-dark; } } \ No newline at end of file diff --git a/codeeditor-app/boot.ts b/codeeditor-app/boot.ts index abb1d96..2d4578c 100644 --- a/codeeditor-app/boot.ts +++ b/codeeditor-app/boot.ts @@ -5,12 +5,14 @@ import { CodeEditor } from './elements/code-editor/code-editor'; import { OutputFrame } from './elements/output-frame/output-frame'; import { NotificationBubbles } from './elements/notification-bubbles/notification-bubbles'; import { NotificationBubble } from './elements/notification-bubbles/notification-bubble'; +import { ResizeHandle } from './elements/resize-handle/resize-handle'; window.customElements.define('app-root', AppRoot); window.customElements.define('code-editor', CodeEditor); window.customElements.define('output-frame', OutputFrame); window.customElements.define('notification-bubbles', NotificationBubbles); window.customElements.define('notification-bubble', NotificationBubble); +window.customElements.define('resize-handle', ResizeHandle); document.body.innerHTML += bootHtml; \ No newline at end of file diff --git a/codeeditor-app/elements/code-editor/code-editor.less b/codeeditor-app/elements/code-editor/code-editor.less index 436801f..05271ad 100644 --- a/codeeditor-app/elements/code-editor/code-editor.less +++ b/codeeditor-app/elements/code-editor/code-editor.less @@ -1,5 +1,16 @@ -monaco-editor { +@import url('../../../shared/theme.less'); + +code-editor { width: 100%; height: 100%; display: block; + background: @editor-bg-white; + color: @primary-text-color-white; +} + +@media (prefers-color-scheme: dark) { + code-editor { + background: @editor-bg-dark; + color: @primary-text-color-dark; + } } \ No newline at end of file diff --git a/codeeditor-app/elements/code-editor/code-editor.ts b/codeeditor-app/elements/code-editor/code-editor.ts index 120249f..0dbffc3 100644 --- a/codeeditor-app/elements/code-editor/code-editor.ts +++ b/codeeditor-app/elements/code-editor/code-editor.ts @@ -73,7 +73,6 @@ export class CodeEditor extends BaseElement { }); this.waitFor(this.outputFrame, () => { - console.log("setting script"); this.outputFrame.setScript(this.input); }); @@ -100,11 +99,7 @@ export class CodeEditor extends BaseElement { }; } - onUpdate(): void { - console.log("APP ROOT UPDATE"); - } - get outputFrame(): OutputFrame { - return this.findSibling("output-frame"); + return this.find("output-frame"); } } \ No newline at end of file diff --git a/codeeditor-app/elements/code-editor/injects/declarations.d.ts b/codeeditor-app/elements/code-editor/injects/declarations.d.ts index dfa3838..27dccda 100644 --- a/codeeditor-app/elements/code-editor/injects/declarations.d.ts +++ b/codeeditor-app/elements/code-editor/injects/declarations.d.ts @@ -4,4 +4,4 @@ declare function rand(from: number, to: number): number; declare function center(): number; declare function width(): number; declare function height(): number; -declare function randomColor(randomOpacity: boolean = true): string; \ No newline at end of file +declare function randomColor(): string; \ No newline at end of file diff --git a/codeeditor-app/elements/code-editor/injects/spiral-boxes-solution.js b/codeeditor-app/elements/code-editor/injects/spiral-boxes-solution.js index c310f52..524c3ed 100644 --- a/codeeditor-app/elements/code-editor/injects/spiral-boxes-solution.js +++ b/codeeditor-app/elements/code-editor/injects/spiral-boxes-solution.js @@ -1,5 +1,5 @@ -const boxSize = 40; -const stepSize = boxSize + boxSize / 4; +const boxSize = 30; +const stepSize = boxSize + boxSize / 1.8; let x = center() - boxSize / 2; let y = center() - boxSize / 2; let turns = 0; @@ -8,7 +8,7 @@ let currentStep = 1; let stepsInCurrentDirection = 1; while (!isOutsizeCanvas()) { - box(x, y, boxSize, boxSize); + box(x, y, boxSize, boxSize, randomColor()); moveAccordingToDirection(); setNextStepAndDirection(); } diff --git a/codeeditor-app/elements/notification-bubbles/notification-bubble.less b/codeeditor-app/elements/notification-bubbles/notification-bubble.less index e9a6b80..672020c 100644 --- a/codeeditor-app/elements/notification-bubbles/notification-bubble.less +++ b/codeeditor-app/elements/notification-bubbles/notification-bubble.less @@ -1,3 +1,5 @@ +@import url('../../../shared/theme.less'); + notification-bubble { margin: 10px; padding: 10px; @@ -39,7 +41,7 @@ notification-bubble.syntax-error { @media (prefers-color-scheme: dark) { notification-bubble { - color: white; + color: @primary-text-color-dark; } notification-bubble.log { diff --git a/codeeditor-app/elements/output-frame/output-frame.less b/codeeditor-app/elements/output-frame/output-frame.less index 1ac7c2b..8817e43 100644 --- a/codeeditor-app/elements/output-frame/output-frame.less +++ b/codeeditor-app/elements/output-frame/output-frame.less @@ -1,8 +1,9 @@ +@import url('../../../shared/theme.less'); + output-frame { width: 100%; height: 100%; display: block; - background-color: #f0f0f0; } output-frame > iframe { @@ -13,9 +14,5 @@ output-frame > iframe { } - @media (prefers-color-scheme: dark) { - output-frame { - background-color: #272727; - } } \ No newline at end of file diff --git a/codeeditor-app/elements/resize-handle/resize-handle.less b/codeeditor-app/elements/resize-handle/resize-handle.less new file mode 100644 index 0000000..650c2ed --- /dev/null +++ b/codeeditor-app/elements/resize-handle/resize-handle.less @@ -0,0 +1,24 @@ +@import url('../../../shared/theme.less'); + +resize-handle { + background: transparent; + position: absolute; + top: 0; + bottom: 0; + width: 8px; + z-index: 9; + cursor: ew-resize; + transition: 1s ease-in; +} + +resize-handle:hover { + background: @primary-interaction-highlight-white; + transition: none; +} + +@media (prefers-color-scheme: dark) { + + resize-handle:hover { + background: @primary-interaction-highlight-dark; + } +} \ No newline at end of file diff --git a/codeeditor-app/elements/resize-handle/resize-handle.ts b/codeeditor-app/elements/resize-handle/resize-handle.ts new file mode 100644 index 0000000..65ddf91 --- /dev/null +++ b/codeeditor-app/elements/resize-handle/resize-handle.ts @@ -0,0 +1,65 @@ +import { BaseElement } from "../../../shared/_base"; +import { CodeEditor } from "../code-editor/code-editor"; +import './resize-handle.less'; + +export class ResizeHandle extends BaseElement { + + public isDowned = false; + + onInit(): void { + this.setDragEvents(); + } + + setDragEvents() { + this.addEventListener("mousedown", (evt: MouseEvent) => { + this.isDowned = true; + this.getIframe().style.display = "none"; + }); + + window.addEventListener("mousemove", (evt: MouseEvent) => { + if (this.isDowned) { + this.setPosition(evt.pageX); + } + }); + + window.addEventListener("mouseup", (evt: MouseEvent) => { + if (this.isDowned) { + this.getIframe().style.display = "block"; + this.isDowned = false; + } + }); + + this.addEventListener("touchstart", (evt: TouchEvent) => { + this.isDowned = true; + this.getIframe().style.display = "none"; + }); + + window.addEventListener("touchmove", (evt: TouchEvent) => { + if (this.isDowned) { + this.setPosition(evt.touches[0].pageX); + } + }); + + window.addEventListener("touchend", (evt: TouchEvent) => { + if (this.isDowned) { + this.getIframe().style.display = "block"; + this.isDowned = false; + } + }); + } + + setPosition(x: number) { + var t = this.getTarget(); + + t.style.minWidth = x + "px"; + t.style.maxWidth = x + "px"; + } + + getTarget() { + return this.find("code-editor"); + } + + getIframe() { + return this.find("iframe"); + } +} \ No newline at end of file diff --git a/outputframe-app/app.less b/outputframe-app/app.less index 239385c..e290628 100644 --- a/outputframe-app/app.less +++ b/outputframe-app/app.less @@ -1,8 +1,11 @@ +@import url('../shared/theme.less'); + html, body { margin: 0; width: 100%; height: 100%; overflow: hidden; + color: @draw-color-white; } *, *::before, *::after { @@ -10,14 +13,12 @@ html, body { } body { - font-family: "Segoe UI", Frutiger, "Frutiger Linotype", "Dejavu Sans", "Helvetica Neue", Arial, sans-serif; - margin: 10px; - background-color: #f0f0f0; + font-family: @primary-font-family; + padding: 10px; } @media (prefers-color-scheme: dark) { body { - background-color: #272727; - color: white; + color: @draw-color-dark; } } \ No newline at end of file diff --git a/outputframe-app/elements/render-canvas/render-canvas.less b/outputframe-app/elements/render-canvas/render-canvas.less index 5a2f517..640c584 100644 --- a/outputframe-app/elements/render-canvas/render-canvas.less +++ b/outputframe-app/elements/render-canvas/render-canvas.less @@ -1,3 +1,5 @@ +@import url('../../../shared/theme.less'); + render-canvas { width: 100%; height: 100%; @@ -16,13 +18,14 @@ render-canvas canvas { left: 50%; transform: translate(-50%, -50%); border: 1px solid #c2c2c2; - background-color: white; + background-color: @median-bg-white; + border-color: @draw-color-white; } @media (prefers-color-scheme: dark) { render-canvas canvas { - background-color: #2c2c2c; - border-color: #3a3a3a; + background-color: @median-bg-dark; + border-color: @draw-color-dark; } } \ No newline at end of file diff --git a/outputframe-app/elements/render-canvas/render-canvas.ts b/outputframe-app/elements/render-canvas/render-canvas.ts index 036c025..ea062bf 100644 --- a/outputframe-app/elements/render-canvas/render-canvas.ts +++ b/outputframe-app/elements/render-canvas/render-canvas.ts @@ -1,3 +1,4 @@ +import { getLessThemeObj } from '../../../shared/less-theme-to-obj'; import { BaseElement } from '../../../shared/_base'; import './render-canvas.less'; @@ -15,6 +16,8 @@ export class RenderCanvas extends BaseElement { public prefersDarkScheme = window.matchMedia("(prefers-color-scheme: dark)"); + private theme: any; + onInit(): void { this.canvas = document.createElement("canvas"); this.ctx = this.canvas.getContext("2d"); @@ -25,6 +28,8 @@ export class RenderCanvas extends BaseElement { this.handleCanvasResize(); }); + this.theme = getLessThemeObj(); + this.handleCanvasResize(); } @@ -42,11 +47,17 @@ export class RenderCanvas extends BaseElement { } } - drawPoly(points: { x: number, y: number }[], color?: string) { + drawPoly(points: { x: number, y: number }[], color?: string | CanvasGradient) { if (this.ctx && this.canvas) { this.canvas.style.display = "block"; - this.ctx.fillStyle = this.getColor(true); - this.ctx.strokeStyle = this.getColor(false, color); + if (color instanceof CanvasGradient) { + //this.ctx.fillStyle = color; + this.ctx.strokeStyle = color; + } + else { + this.ctx.strokeStyle = this.getColor(color); + this.ctx.fillStyle = this.getBackgroundColor(); + } this.ctx.beginPath(); for (var i = 0; i < points.length; i++) { @@ -106,12 +117,20 @@ export class RenderCanvas extends BaseElement { return area; }; + angleBetweenPoints(point1: { x: number, y: number }, point2: { x: number, y: number }) { + // angle in radians + var angleRadians = Math.atan2(point2.y - point1.y, point2.x - point1.x); + + // angle in degrees + return Math.atan2(point2.y - point1.y, point2.x - point1.x) * 180 / Math.PI; + } + executeDrawQueue() { let prevShape: any | null = null; for (let i = 0; i < this.drawQueue.length; i++) { const shape = this.drawQueue[i]; - if (prevShape != null) { + if (prevShape != null && this.ctx) { var prevCenter = this.centerOf(prevShape.points); var thisCenter = this.centerOf(shape.points); @@ -120,8 +139,14 @@ export class RenderCanvas extends BaseElement { y: (prevCenter.y + thisCenter.y) / 2 }; - this.drawPoly([prevCenter, middle], prevShape.color); - this.drawPoly([middle, thisCenter], shape.color); + var grd = this.ctx.createLinearGradient(this.unitsToPx(prevCenter.x), this.unitsToPx(prevCenter.y), this.unitsToPx(thisCenter.x), this.unitsToPx(thisCenter.y)); + grd.addColorStop(0, prevShape?.color ?? this.getColor()); + grd.addColorStop(1, shape?.color ?? this.getColor()); + + this.drawPoly([prevCenter, thisCenter], grd); + + //this.drawPoly([prevCenter, middle], prevShape.color); + //this.drawPoly([middle, thisCenter], shape.color); } prevShape = shape; @@ -131,14 +156,14 @@ export class RenderCanvas extends BaseElement { const shape = this.drawQueue[i]; this.drawPoly(shape.points, shape.color); var thisCenter = this.centerOf(shape.points); - this.drawText(thisCenter.x, thisCenter.y, (i + 1).toString(), shape.points[1].x - shape.points[0].x, shape.color); + this.drawText(thisCenter.x, thisCenter.y, (i + 1).toString(), this.unitsToPx((shape.points[1].x - shape.points[0].x) * 0.6), shape.color); } } drawText(x: number, y: number, text: string, size: number = 20, color?: string) { if (this.ctx && this.canvas) { this.ctx.moveTo(x, y); - this.ctx.fillStyle = this.getColor(false, color); + this.ctx.fillStyle = this.getColor(color); this.ctx.textAlign = 'center'; this.ctx.textBaseline = 'middle'; this.ctx.font = "200 " + size + "px Segoe UI"; @@ -146,8 +171,12 @@ export class RenderCanvas extends BaseElement { } } - getColor(invert: boolean = false, color?: string) { - return color ? color : ((invert ? !this.prefersDarkScheme.matches : this.prefersDarkScheme.matches) ? 'rgba(255,255,255,1)' : 'rgba(44,44,44,1)'); + getColor(color?: string) { + return color ? color : (this.prefersDarkScheme.matches ? this.theme["@draw-color-dark"] : this.theme["@draw-color-white"]); + } + + getBackgroundColor() { + return this.prefersDarkScheme.matches ? this.theme["@median-bg-dark"] : this.theme["@median-bg-white"]; } drawRect(x: number, y: number, width: number, height: number, color?: string) { @@ -164,6 +193,6 @@ export class RenderCanvas extends BaseElement { unitsToPx(unitNumber: number) { var newPPU = Math.min(this.width, this.height) / this.units.width; - return unitNumber * newPPU; + return Math.floor(unitNumber * newPPU); } } \ No newline at end of file diff --git a/outputframe-app/injects/dom-helpers.ts b/outputframe-app/injects/dom-helpers.ts index a3cfc8d..b94bf72 100644 --- a/outputframe-app/injects/dom-helpers.ts +++ b/outputframe-app/injects/dom-helpers.ts @@ -38,6 +38,11 @@ export function executeDrawQueue(): void { renderCanvas.executeDrawQueue(); } -export function getRandomColor(randomOpacity: boolean = true): string { - return "rgba(" + getRandom(0,255) + ", " + getRandom(0,255) + ", " + getRandom(0,255) + ", " + (randomOpacity ? Math.random() + 0.1 : "1") + ")"; +export function getRandomColor(): string { + var prefersDarkScheme = window.matchMedia("(prefers-color-scheme: dark)"); + + var from = prefersDarkScheme.matches ? 127 : 0; + var to = prefersDarkScheme.matches ? 255 : 127; + + return "rgba(" + getRandom(from,to) + ", " + getRandom(from,to) + ", " + getRandom(from,to) + ", " + ("1") + ")"; } \ No newline at end of file diff --git a/shared/less-theme-to-obj.ts b/shared/less-theme-to-obj.ts new file mode 100644 index 0000000..47de29c --- /dev/null +++ b/shared/less-theme-to-obj.ts @@ -0,0 +1,17 @@ + +import themeLess from '!!raw-loader!./theme.less'; + +export function getLessThemeObj(): any { + var result: any = {}; + var lines = themeLess.split(";"); + + for (let i = 0; i < lines.length; i++) { + const line = lines[i].trim(); + var keyValPair = line.split(':'); + + if (keyValPair[0] && keyValPair[1]) + result[keyValPair[0].trim()] = keyValPair[1].trim(); + } + + return result; +} \ No newline at end of file diff --git a/shared/theme.less b/shared/theme.less new file mode 100644 index 0000000..26758cd --- /dev/null +++ b/shared/theme.less @@ -0,0 +1,17 @@ +@primary-bg-color-dark: #2e2e2e; +@primary-border-color-dark: #292929; +@primary-text-color-dark: white; +@primary-interaction-highlight-dark: #385e8f; +@editor-bg-dark: #1e1e1e; +@median-bg-dark: #262626; +@draw-color-dark: #dbdbdb; + +@primary-bg-color-white: #e3e3e3; +@primary-border-color-white: #c2c2c2; +@primary-text-color-white: black; +@primary-interaction-highlight-white: #7274b6; +@editor-bg-white: #fffffe; +@median-bg-white: #f0f0f0; +@draw-color-white: #474747; + +@primary-font-family: "Segoe UI", Frutiger, "Frutiger Linotype", "Dejavu Sans", "Helvetica Neue", Arial, sans-serif; \ No newline at end of file