-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
18 changed files
with
555 additions
and
61 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
30 changes: 30 additions & 0 deletions
30
packages/perspective-viewer-datagrid/src/js/color_utils.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/****************************************************************************** | ||
* | ||
* Copyright (c) 2017, the Perspective Authors. | ||
* | ||
* This file is part of the Perspective library, distributed under the terms of | ||
* the Apache License 2.0. The full license can be found in the LICENSE file. | ||
* | ||
*/ | ||
|
||
export const PLUGIN_SYMBOL = Symbol("Plugin Symbol"); | ||
|
||
export function hexToRgb(hex) { | ||
var bigint = parseInt(hex.trim().slice(1), 16); | ||
var r = (bigint >> 16) & 255; | ||
var g = (bigint >> 8) & 255; | ||
var b = bigint & 255; | ||
return [r, g, b]; | ||
} | ||
|
||
export function rgbaToRgb([r, g, b, a], source = [255, 255, 255]) { | ||
function f(i, c) { | ||
return ((1 - a) * (source[i] / 255) + a * (c / 255)) * 255; | ||
} | ||
|
||
return [f(0, r), f(1, g), f(2, b)]; | ||
} | ||
|
||
export function infer_foreground_from_background([r, g, b]) { | ||
return Math.sqrt(r * r * 0.299 + g * g * 0.587 + b * b * 0.114) > 130 ? "#161616" : "#ffffff"; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
254 changes: 254 additions & 0 deletions
254
packages/perspective-viewer-datagrid/src/js/plugin_menu.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,254 @@ | ||
/****************************************************************************** | ||
* | ||
* Copyright (c) 2017, the Perspective Authors. | ||
* | ||
* This file is part of the Perspective library, distributed under the terms of | ||
* the Apache License 2.0. The full license can be found in the LICENSE file. | ||
* | ||
*/ | ||
|
||
import {hexToRgb} from "./color_utils.js"; | ||
|
||
export const PLUGIN_SYMBOL = Symbol("Plugin Symbol"); | ||
|
||
class PluginMenu extends HTMLElement { | ||
constructor() { | ||
super(); | ||
} | ||
|
||
open(pv_plugin, regularTable, target, column_meta) { | ||
this._pv_plugin = pv_plugin; | ||
this._regularTable = regularTable; | ||
|
||
const rect = target.getBoundingClientRect(); | ||
this.setAttribute("tabindex", "0"); | ||
this.className = "column-plugin-menu"; | ||
this.attachShadow({mode: "open"}); | ||
const pset = regularTable[PLUGIN_SYMBOL] || {}; | ||
const meta = regularTable.getMeta(target); | ||
const column_name = meta.column_header[meta.column_header.length - 1]; | ||
const column_type = pv_plugin._schema[column_name]; | ||
const column_styles = (pset[column_name] = pset[column_name] || {}); | ||
const default_prec = column_type === "float" ? 2 : 0; | ||
const is_numeric = column_type === "float" || column_type === "integer"; | ||
if (!is_numeric) { | ||
this.drop(); | ||
return; | ||
} | ||
|
||
const fixed = (column_styles.fixed + 1 || default_prec + 1) - 1; | ||
const fixed_example = fixed > 0 ? "0." + "0".repeat(fixed - 1) + "1" : "1"; | ||
|
||
let html = ` | ||
<style> | ||
:host { | ||
position: absolute; | ||
left: ${rect.left}px; | ||
top: ${rect.bottom}px; | ||
padding: 6px; | ||
outline: none; | ||
font-family: "Open Sans"; | ||
font-size: 12px; | ||
font-weight: 300; | ||
border: inherit; | ||
box-shadow: 0 2px 4px 0 rgb(0 0 0 / 10%); | ||
} | ||
:host input.parameter { | ||
max-width: 65px; | ||
background: none; | ||
color: inherit; | ||
border: 0px solid transparent; | ||
border-bottom-width: 1px; | ||
border-color: var(--input--border-color); | ||
outline: none; | ||
} | ||
:host input[type=radio], :host input[type=checkbox], :host > div > div > span:first-child { | ||
width: 24px; | ||
margin: 0; | ||
} | ||
:host > div > div { | ||
display: flex; | ||
align-items: center; | ||
height: 24px; | ||
} | ||
:host div.section { | ||
margin-bottom: 8px; | ||
} | ||
:host input[type=color] { | ||
width: 24px; | ||
} | ||
:host .operator { | ||
font-family: "Roboto Mono", monospace; | ||
white-space:pre; | ||
} | ||
:host input.parameter[disabled] { | ||
opacity: 0.5; | ||
} | ||
</style> | ||
<div> | ||
<div> | ||
<input type="checkbox" checked disabled> | ||
</input> | ||
<span id="fixed-examples">Prec ${fixed_example}</span> | ||
</div> | ||
<div class="section"> | ||
<span></span> | ||
<input | ||
id="fixed-param" | ||
value="${fixed}" | ||
class="parameter" | ||
${is_numeric ? "" : "disabled"} | ||
type="number" | ||
min="0" | ||
step="1"> | ||
</input> | ||
</div> | ||
<div> | ||
<input | ||
id="color-selected" | ||
type="checkbox" | ||
${column_styles.pos_color !== undefined ? "checked" : ""}> | ||
</input> | ||
<input | ||
id="color-param" | ||
value="${column_styles?.pos_color !== undefined ? column_styles.pos_color[0] : pv_plugin._pos_color[0]}" | ||
${column_styles.pos_color !== undefined ? "" : "disabled"} | ||
class="parameter" | ||
type="color"> | ||
</input> | ||
<span class="operator"> + / - </span> | ||
<input | ||
id="neg-color-param" | ||
value="${column_styles?.neg_color !== undefined ? column_styles.neg_color[0] : pv_plugin._neg_color[0]}" | ||
${column_styles.neg_color !== undefined ? "" : "disabled"} | ||
class="parameter" | ||
type="color"> | ||
</input> | ||
</div> | ||
<div> | ||
<input | ||
id="color-mode-1" | ||
name="color-mode" | ||
type="radio" | ||
value="foreground" | ||
class="parameter" \ | ||
${column_styles.color_mode !== "background" && column_styles.color_mode !== "gradient" ? "checked" : ""}> | ||
</input> | ||
<span>Foreground</span> | ||
</div> | ||
<div> | ||
<input | ||
id="color-mode-2" | ||
name="color-mode" | ||
type="radio" | ||
value="background" | ||
class="parameter" | ||
${column_styles.color_mode === "background" ? "checked" : ""}> | ||
</input> | ||
<span>Background</span> | ||
</div> | ||
<div> | ||
<input | ||
id="color-mode-3" | ||
name="color-mode" | ||
type="radio" | ||
value="gradient" | ||
class="parameter" | ||
${column_styles.color_mode === "gradient" ? "checked" : ""}> | ||
</input> | ||
<span>Gradient</span> | ||
</div> | ||
<div> | ||
<span></span> | ||
<input | ||
id="gradient-param" | ||
value="${Math.ceil(column_styles.opacity + 1 || column_meta[column_name] + 1) - 1}" | ||
class="parameter" | ||
${column_styles.opacity !== undefined ? "" : "disabled"} | ||
type="number" | ||
min="0"> | ||
</input> | ||
</div> | ||
</div> | ||
`; | ||
|
||
this.shadowRoot.innerHTML += html; | ||
document.body.appendChild(this); | ||
this.shadowRoot.addEventListener( | ||
"input", | ||
(this._changeListener = () => { | ||
const config = {}; | ||
const fixed = parseInt(this.shadowRoot.querySelector(`#fixed-param`).value); | ||
const fixed_example = fixed > 0 ? "Prec 0." + "0".repeat(fixed - 1) + "1" : "Prec 1"; | ||
this.shadowRoot.querySelector(`#fixed-examples`).textContent = fixed_example; | ||
if (isFinite(fixed) && fixed !== default_prec && fixed > -1) { | ||
config.fixed = fixed; | ||
} else { | ||
// TODO validation | ||
} | ||
|
||
if (!this.shadowRoot.querySelector(`#color-mode-1`).checked) { | ||
if (this.shadowRoot.querySelector(`#color-mode-2`).checked) { | ||
config.color_mode = "background"; | ||
} else { | ||
config.color_mode = "gradient"; | ||
} | ||
} | ||
|
||
const opacity = this.shadowRoot.querySelector(`#gradient-param`); | ||
if (config.color_mode === "gradient") { | ||
opacity.disabled = false; | ||
config.opacity = parseInt(opacity.value); | ||
} else { | ||
opacity.value = Math.ceil(column_meta[column_name]); | ||
opacity.disabled = true; | ||
} | ||
|
||
const is_color = this.shadowRoot.querySelector(`#color-selected`).checked; | ||
const color = this.shadowRoot.querySelector(`#color-param`); | ||
const neg_color = this.shadowRoot.querySelector(`#neg-color-param`); | ||
if (is_color) { | ||
color.disabled = neg_color.disabled = false; | ||
config.pos_color = [color.value].concat(hexToRgb(color.value)); | ||
config.neg_color = [neg_color.value].concat(hexToRgb(neg_color.value)); | ||
} else { | ||
color.disabled = neg_color.disabled = true; | ||
} | ||
|
||
regularTable[PLUGIN_SYMBOL] = regularTable[PLUGIN_SYMBOL] || {}; | ||
regularTable[PLUGIN_SYMBOL][column_name] = config; | ||
regularTable.draw({preserve_width: true}); | ||
regularTable.parentElement.dispatchEvent(new Event("perspective-config-update")); | ||
}) | ||
); | ||
|
||
this.addEventListener("blur", (this._drop_handler = this.drop.bind(this))); | ||
regularTable.addEventListener("regular-table-scroll", this._drop_handler); | ||
this.focus(); | ||
} | ||
|
||
drop() { | ||
if (document.body.contains(this)) { | ||
this.removeEventListener("blur", this._drop_handler); | ||
this._regularTable?.removeEventListener("regular-table-scroll", this._drop_handler); | ||
document.body.removeChild(this); | ||
this.shadowRoot.removeEventListener("input", this._changeListener); | ||
} | ||
this._pv_plugin._open_column_styles_menu.pop(); | ||
this._regularTable.draw(); | ||
} | ||
} | ||
|
||
customElements.define("perspective-viewer-datagrid-plugin-menu", PluginMenu); | ||
|
||
export function activate_plugin_menu(regularTable, target, meta) { | ||
const menu = document.createElement("perspective-viewer-datagrid-plugin-menu"); | ||
menu.open(this, regularTable, target, meta); | ||
} |
Oops, something went wrong.