From 01f0dbe1f6fc4c8478c21c2459e799ef97932e58 Mon Sep 17 00:00:00 2001 From: Jordan Eldredge Date: Mon, 28 Jun 2021 20:31:49 -0700 Subject: [PATCH] Use :active state for buttons via CSS variables Also: Ensure the "activated" state of a button is its toggle state not pressed state --- packages/webamp-modern-2/src/index.html | 8 ++++ packages/webamp-modern-2/src/skin/Button.ts | 41 +++++++-------------- packages/webamp-modern-2/src/skin/GuiObj.ts | 27 ++++++++++++++ packages/webamp-modern-2/src/skin/Layer.ts | 3 +- 4 files changed, 50 insertions(+), 29 deletions(-) diff --git a/packages/webamp-modern-2/src/index.html b/packages/webamp-modern-2/src/index.html index fdd6d281..21bf1cbf 100644 --- a/packages/webamp-modern-2/src/index.html +++ b/packages/webamp-modern-2/src/index.html @@ -10,6 +10,14 @@ margin: 0; background-color: rgb(58, 110, 165); } + .webamp--guiobj { + background-image: var(--background-image); + background-position: var(--background-position); + } + .webamp--guiobj:active { + background-image: var(--active-background-image, var(--background-image)); + background-position: var(--active-background-position, var(--background-position)); + } diff --git a/packages/webamp-modern-2/src/skin/Button.ts b/packages/webamp-modern-2/src/skin/Button.ts index be38a82d..8e59c8f3 100644 --- a/packages/webamp-modern-2/src/skin/Button.ts +++ b/packages/webamp-modern-2/src/skin/Button.ts @@ -54,47 +54,34 @@ export default class Button extends GuiObj { getactivated(): boolean { return this._active; } - setactivated(onoff: boolean) { - const previous = this._active; - this._active = onoff; - if (onoff !== previous) { - VM.dispatch(this, "onactivate", [ - { type: "BOOL", value: this._active ? 0 : 1 }, - ]); - this._renderBackground(); + setactivated(_onoff: boolean) { + const onoff = Boolean(_onoff); + + if (onoff !== this._active) { + this._active = onoff; + VM.dispatch(this, "onactivate", [{ type: "BOOL", value: onoff ? 1 : 0 }]); } } _renderBackground() { - let image = this._image; - if (this._active && this._downimage) { - image = this._downimage; + if (this._image != null) { + const bitmap = UI_ROOT.getBitmap(this._image); + this.setBackgroundImage(bitmap); } - if (image != null) { - const bitmap = UI_ROOT.getBitmap(image); - this._div.style.backgroundImage = bitmap.getBackgrondImageCSSAttribute(); - this._div.style.backgroundPosition = bitmap.getBackgrondPositionCSSAttribute(); - if (this._div.style.width === "" && bitmap.getWidth()) { - this._div.style.width = px(bitmap.getWidth()); - } - if (this._div.style.height === "" && bitmap.getHeight()) { - this._div.style.height = px(bitmap.getHeight()); - } + + if (this._downimage != null) { + const downBitmap = UI_ROOT.getBitmap(this._downimage); + this.setActiveBackgroundImage(downBitmap); } } _bindToDom() { // TODO: Cleanup! this._div.addEventListener("mousedown", this._handleMouseDown.bind(this)); - this._div.addEventListener("mouseup", this._handleMouseUp.bind(this)); } _handleMouseDown(e: MouseEvent) { - this.setactivated(true); - } - - _handleMouseUp(e: MouseEvent) { - this.setactivated(false); + this.setactivated(!this._active); } draw() { diff --git a/packages/webamp-modern-2/src/skin/GuiObj.ts b/packages/webamp-modern-2/src/skin/GuiObj.ts index 3b048559..70cebb2a 100644 --- a/packages/webamp-modern-2/src/skin/GuiObj.ts +++ b/packages/webamp-modern-2/src/skin/GuiObj.ts @@ -1,5 +1,6 @@ import { SkinContext } from "../types"; import { assert, num, toBool, px } from "../utils"; +import Bitmap from "./Bitmap"; import { VM } from "./VM"; import XmlObj from "./XmlObj"; @@ -232,8 +233,34 @@ export default class GuiObj extends XmlObj { this._div.style.height = px(this.getheight()); } + setBackgroundImage(bitmap: Bitmap) { + this._div.style.setProperty( + "--background-image", + bitmap.getBackgrondImageCSSAttribute() + ); + this._div.style.setProperty( + "--background-position", + bitmap.getBackgrondPositionCSSAttribute() + ); + } + + // JS Can't set the :active pseudo selector. Instead we have a hard-coded + // pseduo-selector in our stylesheet which references a CSS variable and then + // we control the value of that variable from JS. + setActiveBackgroundImage(bitmap: Bitmap) { + this._div.style.setProperty( + "--active-background-image", + bitmap.getBackgrondImageCSSAttribute() + ); + this._div.style.setProperty( + "--active-background-position", + bitmap.getBackgrondPositionCSSAttribute() + ); + } + draw() { this._div.setAttribute("data-id", this.getId()); + this._div.classList.add("webamp--guiobj"); this._renderVisibility(); this._div.style.position = "absolute"; this._renderAlpha(); diff --git a/packages/webamp-modern-2/src/skin/Layer.ts b/packages/webamp-modern-2/src/skin/Layer.ts index e7701cc7..0adccf35 100644 --- a/packages/webamp-modern-2/src/skin/Layer.ts +++ b/packages/webamp-modern-2/src/skin/Layer.ts @@ -50,8 +50,7 @@ export default class Layer extends GuiObj { this._div.setAttribute("data-obj-name", "Layer"); if (this._image != null) { const bitmap = UI_ROOT.getBitmap(this._image); - this._div.style.backgroundImage = bitmap.getBackgrondImageCSSAttribute(); - this._div.style.backgroundPosition = bitmap.getBackgrondPositionCSSAttribute(); + this.setBackgroundImage(bitmap); } } }