Skip to content

Commit

Permalink
Lots of added colour customisability (#519)
Browse files Browse the repository at this point in the history
Adds the ability to customise the label colors
and line colors of the tree using settings.
Also adds the ability to display searches as points instead of as circles.
Adds the ability to change point colors by clicking on legend
Fixes issues with buttons passing events through to deck below.
  • Loading branch information
theosanderson authored Sep 12, 2023
1 parent 941f03a commit 5dc16ea
Show file tree
Hide file tree
Showing 15 changed files with 561 additions and 151 deletions.
2 changes: 2 additions & 0 deletions taxonium_component/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,13 @@
"classnames": "^2.3.2",
"deck.gl": "=8.6.6",
"react-circular-progressbar": "^2.1.0",
"react-color": "^2.19.3",
"react-debounce-input": "^3.3.0",
"react-hot-toast": "^2.4.1",
"react-icons": "^4.8.0",
"react-modal": "^3.16.1",
"react-spinners": "^0.13.8",
"react-tabs": "4",
"react-tooltip": "^4.2.21",
"readable-web-to-node-stream": "^3.0.2",
"sb": "^7.0.14",
Expand Down
102 changes: 66 additions & 36 deletions taxonium_component/src/Deck.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { TreenomeButtons } from "./components/TreenomeButtons";
import TreenomeModal from "./components/TreenomeModal";
import FirefoxWarning from "./components/FirefoxWarning";
import { JBrowseErrorBoundary } from "./components/JBrowseErrorBoundary";
import ColorSettingModal from "./components/ColorSettingModal";
import Key from "./components/Key";

const MemoizedKey = React.memo(Key);
Expand All @@ -42,10 +43,14 @@ function Deck({
isCurrentlyOutsideBounds,
deckRef,
jbrowseRef,
setAdditionalColorMapping,
}) {
const zoomReset = view.zoomReset;
const snapshot = useSnapshot(deckRef);
const [deckSettingsOpen, setDeckSettingsOpen] = useState(false);
const [colorSettingOpen, setColorSettingOpen] = useState(false);
const [currentColorSettingKey, setCurrentColorSettingKey] = useState("a");
const [hoveredKey, setHoveredKey] = useState(null);
const [treenomeSettingsOpen, setTreenomeSettingsOpen] = useState(false);

//console.log("DATA is ", data);
Expand Down Expand Up @@ -187,6 +192,7 @@ function Deck({
treenomeState,
treenomeReferenceInfo,
setTreenomeReferenceInfo,
hoveredKey,
});
// console.log("deck refresh");

Expand Down Expand Up @@ -254,6 +260,65 @@ function Deck({
deckSettingsOpen={deckSettingsOpen}
setDeckSettingsOpen={setDeckSettingsOpen}
settings={settings}
noneColor={colorHook.toRGB("None")}
setNoneColor={(color) => {
setAdditionalColorMapping((x) => {
return { ...x, None: color };
});
}}
/>
<ColorSettingModal
isOpen={colorSettingOpen}
setIsOpen={setColorSettingOpen}
color={colorHook.toRGB(currentColorSettingKey)}
setColor={(color) => {
setAdditionalColorMapping((x) => {
return { ...x, [currentColorSettingKey]: color };
});
}}
title={currentColorSettingKey}
/>
<NodeHoverTip
hoverInfo={hoverInfo}
hoverDetails={hoverDetails}
colorHook={colorHook}
colorBy={colorBy}
config={config}
filterMutations={settings.filterMutations}
deckSize={deckSize}
/>
<TreenomeMutationHoverTip
hoverInfo={hoverInfo}
hoverDetails={hoverDetails}
colorHook={colorHook}
colorBy={colorBy}
config={config}
treenomeReferenceInfo={treenomeReferenceInfo}
/>
<MemoizedKey
keyStuff={keyStuff}
colorByField={colorBy.colorByField}
colorByGene={colorBy.colorByGene}
colorByPosition={colorBy.colorByPosition}
config={config}
setCurrentColorSettingKey={setCurrentColorSettingKey}
setColorSettingOpen={setColorSettingOpen}
hoveredKey={hoveredKey}
setHoveredKey={setHoveredKey}
/>
<DeckButtons
// we want this to intercept all mouse events
// so that we can prevent the default behavior
// of the browser

zoomReset={zoomReset}
zoomIncrement={zoomIncrement}
zoomAxis={zoomAxis}
setZoomAxis={setZoomAxis}
snapshot={snapshot}
loading={data.status === "loading"}
requestOpenSettings={() => setDeckSettingsOpen(true)}
settings={settings}
/>
<DeckGL
pickingRadius={10}
Expand Down Expand Up @@ -314,42 +379,7 @@ function Deck({
settings={settings}
/>
</View>
<View id="main">
<NodeHoverTip
hoverInfo={hoverInfo}
hoverDetails={hoverDetails}
colorHook={colorHook}
colorBy={colorBy}
config={config}
filterMutations={settings.filterMutations}
deckSize={deckSize}
/>
<TreenomeMutationHoverTip
hoverInfo={hoverInfo}
hoverDetails={hoverDetails}
colorHook={colorHook}
colorBy={colorBy}
config={config}
treenomeReferenceInfo={treenomeReferenceInfo}
/>
<MemoizedKey
keyStuff={keyStuff}
colorByField={colorBy.colorByField}
colorByGene={colorBy.colorByGene}
colorByPosition={colorBy.colorByPosition}
config={config}
/>
<DeckButtons
zoomReset={zoomReset}
zoomIncrement={zoomIncrement}
zoomAxis={zoomAxis}
setZoomAxis={setZoomAxis}
snapshot={snapshot}
loading={data.status === "loading"}
requestOpenSettings={() => setDeckSettingsOpen(true)}
settings={settings}
/>
</View>
<View id="main"></View>
</DeckGL>
</div>
);
Expand Down
7 changes: 5 additions & 2 deletions taxonium_component/src/Taxonium.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,11 @@ function Taxonium({
configUrl
);
const colorBy = useColorBy(config, query, updateQuery);
const [additionalColorMapping, setAdditionalColorMapping] = useState({});
const colorMapping = useMemo(() => {
return config.colorMapping ? config.colorMapping : {};
}, [config.colorMapping]);
const initial = config.colorMapping ? config.colorMapping : {};
return { ...initial, ...additionalColorMapping };
}, [config.colorMapping, additionalColorMapping]);
const colorHook = useColor(colorMapping);

//TODO: this is always true for now
Expand Down Expand Up @@ -193,6 +195,7 @@ function Taxonium({
treenomeState={treenomeState}
deckRef={deckRef}
jbrowseRef={jbrowseRef}
setAdditionalColorMapping={setAdditionalColorMapping}
/>
</div>

Expand Down
84 changes: 84 additions & 0 deletions taxonium_component/src/components/ColorPicker.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import React, { useState } from "react";
import { SketchPicker } from "react-color";

const rgbToList = (rgb) => {
return [rgb.r, rgb.g, rgb.b];
};
const listToRgb = (list) => {
const color = { r: list[0], g: list[1], b: list[2] };
return color;
};

function ColorPicker({ color, setColor }) {
const rgbColor = listToRgb(color);
const [showPicker, setShowPicker] = useState(false);

const togglePicker = () => {
setShowPicker(!showPicker);
};

const handleClose = () => {
setShowPicker(false);
};

const handleColorChange = (newColor) => {
setColor(rgbToList(newColor.rgb));
};

if (!showPicker) {
return (
<div className="inline-block">
<div
style={{
padding: "5px",
background: "#fff",
borderRadius: "1px",
boxShadow: "0 0 0 1px rgba(0,0,0,.1)",
display: "inline-block",
cursor: "pointer",
}}
onClick={togglePicker}
>
<div
style={{
width: "36px",
height: "14px",
borderRadius: "2px",
background: `rgba(${rgbColor.r},${rgbColor.g},${rgbColor.b},${
rgbColor.a || 1
})`,
}}
/>
</div>
</div>
);
}

return (
<div
style={{
position: "absolute",
zIndex: "2",
}}
>
<div
style={{
position: "fixed",
top: "0px",
right: "0px",
bottom: "0px",
left: "0px",
}}
onClick={handleClose}
/>
<SketchPicker
color={rgbColor}
onChange={handleColorChange}
presetColors={[]}
disableAlpha={true}
/>
</div>
);
}

export default ColorPicker;
44 changes: 44 additions & 0 deletions taxonium_component/src/components/ColorSettingModal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from "react";
import Modal from "react-modal";
import ColorPicker from "./ColorPicker";

const modalStyle = {
content: {
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
backgroundColor: "#fafafa",
border: "1px solid #e2e8f0",
borderRadius: "8px",
padding: "20px",
maxWidth: "400px",
},
overlay: {
backgroundColor: "rgba(100, 100, 100, 0.3)",
zIndex: 1000,
},
};

const ColorSettingModal = ({ isOpen, setIsOpen, color, setColor, title }) => {
return (
<Modal
isOpen={isOpen}
style={modalStyle}
onRequestClose={() => setIsOpen(false)}
contentLabel={title}
>
<h2 className="font-medium mb-5 text-lg">{title}</h2>

<div className="space-y-3">
<div>
<label>
Select Color:
<ColorPicker color={color} setColor={setColor} />
</label>
</div>
</div>
</Modal>
);
};

export default ColorSettingModal;
7 changes: 6 additions & 1 deletion taxonium_component/src/components/DeckButtons.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ const TaxButton = ({ children, onClick, title }) => {
shadow-md "
onClick={onClick}
title={title}
style={{
pointerEvents: "auto",
}}
>
{children}
</button>
Expand All @@ -41,7 +44,8 @@ export const DeckButtons = ({
position: "absolute",
right: "0em",
bottom: "0em",
zIndex: 10,
zIndex: 2,
pointerEvents: "none",
}}
className="flex flex-col items-end"
>
Expand All @@ -63,6 +67,7 @@ export const DeckButtons = ({
"
style={{
fontSize: ".7em",
pointerEvents: "auto",
boxShadow: "0px -3px 4px 4px rgba(255, 255, 255, 1)",
}}
>
Expand Down
Loading

1 comment on commit 5dc16ea

@vercel
Copy link

@vercel vercel bot commented on 5dc16ea Sep 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.