Skip to content

Commit

Permalink
Reorganize the viewer actions & color bar
Browse files Browse the repository at this point in the history
  • Loading branch information
Luthaf committed Dec 14, 2023
1 parent 1188bdc commit 5684af7
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 77 deletions.
6 changes: 3 additions & 3 deletions src/map/marker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export class MarkerData {

constructor(guid: string, color: string, environment: number, visible: boolean = true) {
const marker = document.createElement('div');
marker.classList.add('chsp-structure-marker');
marker.classList.add('chsp-pin-marker', 'chsp-map-pin-marker');
marker.id = `chsp-selected-${guid}`;
marker.style.backgroundColor = color;
this.marker = marker;
Expand Down Expand Up @@ -52,12 +52,12 @@ export class MarkerData {

// Changes the marker properties to active marker properties
public activate(): void {
this.marker.classList.toggle('chsp-active-structure', true);
this.marker.classList.toggle('chsp-active-pin', true);
}

// Changes the marker properties to inactive marker properties
public deactivate(): void {
this.marker.classList.toggle('chsp-active-structure', false);
this.marker.classList.toggle('chsp-active-pin', false);
}

// Remove this marker
Expand Down
32 changes: 21 additions & 11 deletions src/static/chemiscope.css
Original file line number Diff line number Diff line change
Expand Up @@ -54,49 +54,59 @@
visibility: hidden;
background: #69738a;
color: white;
padding: 8px 10px;
padding: 6px;
font-size: 12px;
line-height: 12px;
white-space: nowrap;
margin-right: -18px;
border-radius: 2px;
text-align: center;
display: inline-block;
top: 30px;
left: -60px;
/* Position the tooltip text - see examples below! */
width: 9em;
position: absolute;
z-index: 100000;
}

.chsp-tooltip-right {
top: 0px;
right: -9.5em;
}

.chsp-tooltip-below {
top: 35px;
left: -3.5em;
}

.chsp-has-tooltip:hover .chsp-tooltip {
visibility: visible;
}

.chsp-structure-marker {
.chsp-pin-marker {
border-radius: 50%;
border: solid 1px black;
--size: 12px;
width: var(--size);
height: var(--size);
z-index: 10;
}

.chsp-map-pin-marker {
position: absolute;
/* ensure the top/right/left/bottom positioning is relative to the center of the div */
transform: translate(calc(-50% + var(--size)), -50%);
z-index: 10;
}

.chsp-structure-marker:hover {
.chsp-pin-marker:hover {
--size: 20px;
cursor: pointer;
}

/* This class is added on top of .chsp-structure-marker for the active structure */
.chsp-active-structure {
/* This class is added on top of .chsp-pin-marker for the active pinned structure/environment */
.chsp-active-pin {
border-width: 2px;
--size: 20px;
}

.chsp-active-structure:hover {
.chsp-active-pin:hover {
--size: 22px;
cursor: default;
}
Expand Down
28 changes: 14 additions & 14 deletions src/structure/grid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ export class ViewersGrid {
const changeClasses = (guid: string, toggle: boolean) => {
// change tooltip text in the active marker
const button = this._getById(`chsp-activate-${guid}`);
button.classList.toggle('chsp-active-structure', toggle);
button.classList.toggle('chsp-active-pin', toggle);
assert(button.parentElement !== null);
const tooltip = button.parentElement.querySelector('.chsp-tooltip');
assert(tooltip !== null);
Expand Down Expand Up @@ -612,16 +612,16 @@ export class ViewersGrid {
// because it will conflict with the button behavior

// add a button to set the cell/viewer as the active one
const template = document.createElement('template');
color = this._getNextColor();
const template = document.createElement('template');
template.innerHTML = `<div
class="chsp-has-tooltip"
style="position: absolute; top: 7px; right: 160px;">
class="chsp-has-tooltip chsp-viewer-button chsp-viewer-action-button"
style="position: absolute; top: 6px; left: 6px; display: flex">
<div id="chsp-activate-${cellGUID}"
class="chsp-structure-marker"
style="background-color: ${color}; top: 13px; right: 0px;"
class="chsp-pin-marker"
style="background-color: ${color}; position: relative; margin: auto;"
></div>
<span class="chsp-tooltip">WILL BE FILLED LATER</span>
<span class="chsp-tooltip chsp-tooltip-right">WILL BE FILLED LATER</span>
</div>`;
const activate = template.content.firstChild as HTMLElement;
activate.onclick = () => {
Expand All @@ -636,9 +636,9 @@ export class ViewersGrid {
// add a button to remove the cell
template.innerHTML = `<button
class="btn btn-light btn-sm chsp-has-tooltip chsp-viewer-button chsp-viewer-action-button"
style="top: 6px; right: 41px;">
style="top: 6px; right: 32px;">
<span>${CLOSE_SVG}</span>
<span class="chsp-tooltip">Remove viewer</span>
<span class="chsp-tooltip chsp-tooltip-below">Remove viewer</span>
</button>`;
const remove = template.content.firstChild as HTMLElement;
remove.onclick = () => {
Expand All @@ -656,9 +656,9 @@ export class ViewersGrid {
// add a button to duplicate the cell
template.innerHTML = `<button
class="btn btn-light btn-sm chsp-has-tooltip chsp-viewer-button chsp-viewer-action-button"
style="top: 6px; right: 76px;">
<span>${DUPLICATE_SVG}</span>
<span class="chsp-tooltip">Duplicate viewer</span>
style="top: 6px; right: 60px;">
<span style="position: absolute; top: 2px; right: 5px;">${DUPLICATE_SVG}</span>
<span class="chsp-tooltip chsp-tooltip-below">Duplicate viewer</span>
</button>`;
const duplicate = template.content.firstChild as HTMLElement;

Expand All @@ -674,9 +674,9 @@ export class ViewersGrid {
// add a button to download PNG
template.innerHTML = `<button
class="btn btn-light btn-sm chsp-has-tooltip chsp-viewer-button chsp-viewer-action-button"
style="top: 6px; right: 111px;">
style="top: 6px; right: 90px;">
<span>${PNG_SVG}</span>
<span class="chsp-tooltip">Download PNG</span>
<span class="chsp-tooltip chsp-tooltip-below">Download PNG</span>
</button>`;
const downloadPNG = template.content.firstChild as HTMLElement;

Expand Down
154 changes: 105 additions & 49 deletions src/structure/viewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,8 @@ export class MoleculeViewer {
},
{ capture: true }
);

window.addEventListener('resize', () => this.resize());
}

/**
Expand Down Expand Up @@ -853,13 +855,6 @@ export class MoleculeViewer {
});

// ======= color settings
// To call the function above if the window is resized
window.addEventListener('resize', () => {
if (this._options.color.property.value !== 'element') {
this._updateColorBar();
}
});

// setup state when the property changes
const colorPropertyChanged = () => {
const property = this._options.color.property.value;
Expand Down Expand Up @@ -1714,39 +1709,23 @@ export class MoleculeViewer {
* properties displaying the minimum and maximum values
*/
private _addColorBar(): ColorBar {
let min = this._options.color.min.value;
let max = this._options.color.max.value;
let mid = (min + max) / 2;
min = Math.round(min * 100) / 100;
mid = Math.round(mid * 100) / 100;
max = Math.round(max * 100) / 100;
const palette = this._options.color.palette.value;
const title = this._colorTitle();

// To take the width of the viewer.
const screenWidth = this._viewer.container?.clientWidth;
// To take the height of the viewer.
const screenHeight = this._viewer.container?.clientHeight;
assert(screenWidth !== undefined && screenHeight !== undefined);
let gradWidth = screenWidth - 205;
let gradHeight = 0.02 * screenHeight + 6;
let gradPosShift = 0;
if (gradWidth > 250) {
gradWidth = 250;
}
if (gradWidth < 60) {
gradWidth = 60;
gradPosShift = 30;
}
if (gradHeight > 20) {
gradHeight = 20;
}
const viewerWidth = this._viewer.container?.clientWidth;
const viewerHeight = this._viewer.container?.clientHeight;
assert(viewerWidth !== undefined && viewerHeight !== undefined);
const width = 20;
const horizontalShift = 35;

const titleHeight = 30;
const height = viewerHeight - (titleHeight + 50);

// Create the color bar gradient using canvas
const gradientCanvas = document.createElement('canvas');

gradientCanvas.width = gradWidth;
gradientCanvas.height = gradHeight;
gradientCanvas.width = width;
gradientCanvas.height = height;
const mapColor = COLOR_MAPS[palette];

const ctx = gradientCanvas.getContext('2d');
Expand All @@ -1756,33 +1735,61 @@ export class MoleculeViewer {
}

// Create a linear gradient from colorStart to colorEnd
const gradient = ctx.createLinearGradient(0, 0, gradWidth, 0);
const gradient = ctx.createLinearGradient(0, height, 0, 0);
for (let c = 0; c < mapColor.length; c++) {
gradient.addColorStop(mapColor[c][0], mapColor[c][1]);
}

ctx.fillStyle = gradient;
ctx.fillRect(0, 0, gradWidth, gradHeight);
ctx.fillRect(0, 0, width, height);

const min = this._options.color.min.value;
const max = this._options.color.max.value;
const mid = (min + max) / 2;

return {
min: this._viewer.addLabel(
JSON.stringify(min),
this._colorBarLabelsSpec(20, gradHeight + gradPosShift + 2)
fixedWidthFloat(min),
this._colorBarLabelsSpec({
x: viewerWidth - horizontalShift,
y: viewerHeight - (titleHeight + 8),
alignment: 'centerLeft',
fontSize: 14,
})
),
mid: this._viewer.addLabel(
JSON.stringify(mid),
this._colorBarLabelsSpec(20 + gradWidth / 2, gradHeight + gradPosShift + 2)
fixedWidthFloat(mid),
this._colorBarLabelsSpec({
x: viewerWidth - horizontalShift,
y: viewerHeight - (titleHeight + height / 2),
alignment: 'centerLeft',
fontSize: 14,
})
),
max: this._viewer.addLabel(
JSON.stringify(max),
this._colorBarLabelsSpec(20 + gradWidth, gradHeight + gradPosShift + 2)
fixedWidthFloat(max),
this._colorBarLabelsSpec({
x: viewerWidth - horizontalShift,
y: viewerHeight - (titleHeight + height - 8),
alignment: 'centerLeft',
fontSize: 14,
})
),
property: this._viewer.addLabel(
title,
this._colorBarLabelsSpec(20 + gradWidth / 2, gradHeight + gradPosShift + 16)
this._colorBarLabelsSpec({
x: viewerWidth - 6,
y: viewerHeight - 15,
alignment: 'centerRight',
fontSize: 16,
})
),
gradient: this._viewer.addLabel('.', {
position: new $3Dmol.Vector3(20, gradPosShift + 4, 0),
position: new $3Dmol.Vector3(
viewerWidth - (width + horizontalShift),
viewerHeight - (height + titleHeight),
0
),
backgroundImage: gradientCanvas,
borderColor: 'black',
borderOpacity: 1,
Expand All @@ -1797,16 +1804,22 @@ export class MoleculeViewer {
}

/** Generate a LabelSpec for the key values in the color bar */
private _colorBarLabelsSpec(xPosition: number, yPosition: number): $3Dmol.LabelSpec {
private _colorBarLabelsSpec(options: {
x: number;
y: number;
alignment: string;
fontSize: number;
}): $3Dmol.LabelSpec {
return {
alignment: 'topCenter',
position: new $3Dmol.Vector3(xPosition, yPosition, 0),
alignment: options.alignment,
position: new $3Dmol.Vector3(options.x, options.y, 0),
font: 'sans',
fontColor: 'black',
fontSize: 14,
fontSize: options.fontSize,
showBackground: false,
inFront: true,
useScreen: true,
backgroundColor: 'red',
};
}

Expand All @@ -1823,8 +1836,51 @@ export class MoleculeViewer {

private _updateColorBar() {
this._deleteColorBar();
if (this._options.color.property.value !== 'element') {
this._colorBar = this._addColorBar();
// if (this._options.color.property.value !== 'element') {
this._colorBar = this._addColorBar();
// }
}
}

/** Try to format a float to ensure it fits in a 4 characters limit */
function fixedWidthFloat(value: number): string {
if (value === 0) {
return '0';
} else if (value > 0) {
// we can use the full 4 characters for the number
if (value < 10000 && value > 0.009) {
if (Number.isInteger(value)) {
return value.toString();
} else {
// convert to fixed format with 3 decimals, then truncate to fit
// in 4 characters
let result = value.toFixed(3).substring(0, 4);
if (result[3] === '.') {
result = result.substring(0, 3);
}
return result;
}
} else {
// convert to exponential format with no decimal part
return value.toExponential(0).replace('+', '');
}
} else {
// we only have 3 characters, we need one for the '-' sign
if (value > -1000 && value < -0.09) {
if (Number.isInteger(value)) {
return value.toString();
} else {
// convert to fixed format with 2 decimals, then truncate to fit in
// 4 characters
let result = value.toFixed(3).substring(0, 4);
if (result[3] === '.') {
result = result.substring(0, 3);
}
return result;
}
} else {
// convert to exponential format with no decimal part
return value.toExponential(0).replace('+', '');
}
}
}

0 comments on commit 5684af7

Please sign in to comment.