- Modify the compare script to output more details of a comparison. This will include the source/golden directory, the comparison directory (the new renderings), and a file path to difference images if the golden does not match the rendered image. - The image_diff script can now output a TIFF that is the difference of two input TIFFs. - Add a viewer for examining the differences between rendered output and golden images. - The viewer consists of a simple server of web API endpoints for querying difference results (along with rendered images in TIFF). - And a web-based (html + lit-element) UI for looking at the rendered images and differences.
226 lines
6.0 KiB
JavaScript
226 lines
6.0 KiB
JavaScript
// Copyright (C) 2025 The Android Open Source Project
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
import { LitElement, html, css } from "https://cdn.jsdelivr.net/gh/lit/dist@3/all/lit-all.min.js";
|
|
|
|
// Generated by Gemini
|
|
export class RadioButtonGroup extends LitElement {
|
|
static styles = css`
|
|
:host {
|
|
display: block;
|
|
font-family: sans-serif;
|
|
}
|
|
.radio-group-container {
|
|
display: flex;
|
|
flex-direction: row;
|
|
}
|
|
label {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-bottom: 8px;
|
|
cursor: pointer;
|
|
padding: 8px;
|
|
border-radius: 4px;
|
|
transition: background-color 0.2s ease-in-out;
|
|
}
|
|
label:hover {
|
|
background-color: #f0f0f0;
|
|
}
|
|
input[type="radio"] {
|
|
margin-right: 8px;
|
|
cursor: pointer;
|
|
/* Custom radio button appearance */
|
|
appearance: none;
|
|
-webkit-appearance: none;
|
|
width: 18px;
|
|
height: 18px;
|
|
border: 2px solid #ccc;
|
|
border-radius: 50%;
|
|
outline: none;
|
|
transition: border-color 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
|
|
}
|
|
input[type="radio"]:checked {
|
|
border-color: #656565;
|
|
background-color: #656565; /* Optional: fill color when checked */
|
|
}
|
|
input[type="radio"]:checked::before {
|
|
content: '';
|
|
display: block;
|
|
width: 8px;
|
|
height: 8px;
|
|
margin: 3px; /* Adjust to center the dot */
|
|
background-color: white;
|
|
border-radius: 50%;
|
|
}
|
|
input[type="radio"]:focus {
|
|
box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25);
|
|
}
|
|
.label-text {
|
|
font-size: 1rem;
|
|
}
|
|
`;
|
|
static properties = {
|
|
/**
|
|
* An array of strings representing the choices for the radio buttons.
|
|
* @type {Array<string>}
|
|
*/
|
|
choices: { type: Array },
|
|
|
|
/**
|
|
* The name for the radio button group. This is important for accessibility
|
|
* and ensuring only one radio button in the group can be selected.
|
|
* @type {string}
|
|
*/
|
|
name: { type: String },
|
|
|
|
/**
|
|
* The currently selected value.
|
|
* @type {string}
|
|
*/
|
|
value: { type: String, reflect: true },
|
|
|
|
/**
|
|
* The label or title for the radio group.
|
|
* @type {string}
|
|
*/
|
|
groupLabel: { type: String }
|
|
};
|
|
|
|
constructor() {
|
|
super();
|
|
this.choices = [];
|
|
this.name = 'radio-group'; // Default name
|
|
this.value = '';
|
|
this.groupLabel = '';
|
|
}
|
|
|
|
_handleChange(event) {
|
|
const selectedValue = event.target.value;
|
|
if (this.value !== selectedValue) {
|
|
this.value = selectedValue;
|
|
// Dispatch a custom event with the new value
|
|
this.dispatchEvent(new CustomEvent('radio-change', {
|
|
detail: { value: this.value, radioId: this.id },
|
|
bubbles: true, // Allows the event to bubble up through the DOM
|
|
composed: true // Allows the event to cross shadow DOM boundaries
|
|
}));
|
|
}
|
|
}
|
|
|
|
render() {
|
|
return html`
|
|
<div class="radio-group-container" role="radiogroup" aria-labelledby="group-label">
|
|
${this.groupLabel ? html`<span id="group-label" class="group-label">${this.groupLabel}</span>` : ''}
|
|
${this.choices.map(choice => html`
|
|
<label>
|
|
<input
|
|
type="radio"
|
|
name=${this.name}
|
|
.value=${choice}
|
|
.checked=${choice === this.value}
|
|
@change=${this._handleChange}
|
|
>
|
|
<span class="label-text">${choice}</span>
|
|
</label>
|
|
`)}
|
|
</div>
|
|
`;
|
|
}
|
|
}
|
|
|
|
customElements.define('radio-button-group', RadioButtonGroup);
|
|
|
|
// Generated by Gemini with some modifications
|
|
class ModalDialog extends LitElement {
|
|
static styles = css`
|
|
:host {
|
|
display: none; /* Hidden by default */
|
|
}
|
|
|
|
:host([open]) {
|
|
display: block; /* Show when open attribute is present */
|
|
}
|
|
|
|
.backdrop {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100vw;
|
|
height: 100vh;
|
|
background-color: rgba(0, 0, 0, 0.5); /* Semi-transparent black */
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
z-index: 1000; /* Ensure it's on top */
|
|
}
|
|
|
|
.dialog {
|
|
background-color: white;
|
|
padding: 20px;
|
|
border-radius: 8px;
|
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
min-width: 300px; /* Or your desired width */
|
|
z-index: 1001; /* Above the backdrop */
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
margin: 0 15px;
|
|
}
|
|
`;
|
|
|
|
static get properties() {
|
|
return {
|
|
open: { type: Boolean, reflect: true },
|
|
};
|
|
}
|
|
|
|
constructor() {
|
|
super();
|
|
this.open = false;
|
|
}
|
|
|
|
_handleBackdropClick(event) {
|
|
// Close only if the click is directly on the backdrop, not on the dialog itself
|
|
if (event.target === this.shadowRoot.querySelector('.backdrop')) {
|
|
this.open = false;
|
|
this.dispatchEvent(new CustomEvent('dialog-closed', { bubbles: true, composed: true }));
|
|
}
|
|
}
|
|
|
|
_handleDialogClick(event) {
|
|
// Prevent clicks inside the dialog from bubbling up to the backdrop
|
|
event.stopPropagation();
|
|
}
|
|
|
|
render() {
|
|
if (!this.open) {
|
|
return html``;
|
|
}
|
|
|
|
return html`
|
|
<div class="backdrop" @click="${this._handleBackdropClick}">
|
|
<div class="dialog" @click="${this._handleDialogClick}">
|
|
<slot name="header"><h2>Default Header</h2></slot>
|
|
<slot>
|
|
<p>This is the default content of the modal.</p>
|
|
</slot>
|
|
<slot name="footer">
|
|
</slot>
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
}
|
|
customElements.define('modal-dialog', ModalDialog);
|