From e0c6d0ec5091536734288ab06ad4587b43387d2f Mon Sep 17 00:00:00 2001 From: "Thomas F. K. Jorna" Date: Thu, 29 Jul 2021 06:07:45 +0200 Subject: handled all the link color cases --- components/config.ts | 28 +-- components/tweaks.tsx | 464 +++++++++++++++++++++++++++++++++----------------- pages/_app.tsx | 3 +- pages/index.tsx | 122 ++++++++++--- 4 files changed, 409 insertions(+), 208 deletions(-) diff --git a/components/config.ts b/components/config.ts index c6f581d..2c7a1b6 100644 --- a/components/config.ts +++ b/components/config.ts @@ -84,33 +84,9 @@ export const initialVisuals = { algorithms: algorithms, algorithmOptions: options, algorithmName: 'CubicOut', - linkColorScheme: 'grey', + linkColorScheme: '500', nodeColorScheme: ['gray', 'red', 'orange', 'yellow', 'green', 'cyan', 'blue', 'pink', 'purple'], nodeHighlight: '', linkHighlight: '', -} - -export type Visuals = { - particles: boolean - particlesNumber: number - particlesWidth: number - linkOpacity: number - linkWidth: number - nodeRel: number - nodeOpacity: number - nodeResolution: number - labels: number - labelScale: number - highlight: boolean - highlightNodeSize: number - highlightLinkSize: number - highlightAnim: boolean - animationSpeed: number - algorithms: typeof algorithms - algorithmOptions: typeof options - algorithmName: string - linkColorScheme: string - nodeColorScheme: string[] - nodeHighlight: string - linkHighlight: string + backgroundColor: 'white', } diff --git a/components/tweaks.tsx b/components/tweaks.tsx index 9da387b..709cbf5 100644 --- a/components/tweaks.tsx +++ b/components/tweaks.tsx @@ -4,6 +4,8 @@ import { ChevronDownIcon, SettingsIcon, InfoOutlineIcon, + RepeatIcon, + ArrowRightIcon, } from '@chakra-ui/icons' import { Accordion, @@ -48,7 +50,7 @@ export interface TweakProps { setThreeDim: (newValue: boolean) => void filter: typeof initialFilter setFilter: any - visuals: Visuals + visuals: typeof initialVisuals setVisuals: any } @@ -58,6 +60,7 @@ export const Tweaks = (props: TweakProps) => { const [showTweaks, setShowTweaks] = useState(true) const { highlightColor, setHighlightColor } = useContext(ThemeContext) const colorList = ['red', 'orange', 'yellow', 'green', 'cyan', 'blue', 'pink', 'purple', 'gray'] + const grays = ['100', '200', '300', '400', '500', '600', '700', '800', '900'] return ( <> { Visual - } - align="stretch" - paddingLeft={7} - color="gray.800" - > - + + @@ -314,6 +310,39 @@ export const Tweaks = (props: TweakProps) => { Nodes + + } + variant="ghost" + onClick={() => { + const arr = visuals.nodeColorScheme ?? [] + setVisuals({ + ...visuals, + //shuffle that guy + //definitely thought of this myself + nodeColorScheme: arr + .map((x) => [Math.random(), x]) + .sort(([a], [b]) => a - b) + .map(([_, x]) => x), + }) + }} + /> + + + } + size="sm" + variant="ghost" + onClick={() => { + const arr = visuals.nodeColorScheme ?? [] + setVisuals({ + ...visuals, + nodeColorScheme: [...arr.slice(1, arr.length), arr[0]], + }) + }} + /> + { Links - + } > - - {visuals.linkColorScheme[0]!.toUpperCase() + - visuals.linkColorScheme!.slice(1)} - + + {visuals.linkColorScheme ? ( + + ) : ( + + {visuals.nodeColorScheme.map((color) => ( + + ))} + + )} + - - setPhysics({ ...physics, labels: 1 })}> - Match Nodes - - setPhysics({ ...physics, labels: 2 })}> - Gray + + + setVisuals({ ...visuals, linkColorScheme: '' }) + } + justifyContent="space-between" + alignItems="center" + display="flex" + > + Match nodes + + {visuals.nodeColorScheme.map((color) => ( + + ))} + + {grays.map((color) => ( + + setVisuals({ + ...visuals, + linkColorScheme: color, + }) + } + justifyContent="space-between" + alignItems="center" + display="flex" + > + {color[0]!.toUpperCase() + color!.slice(1)} + + + ))} @@ -537,172 +629,228 @@ export const Tweaks = (props: TweakProps) => { + + Background + + } + > + { + + } + + + {grays.map((color) => ( + + setVisuals({ ...visuals, backgroundColor: color }) + } + justifyContent="space-between" + alignItems="center" + display="flex" + > + {color[0]!.toUpperCase() + color!.slice(1)} + + + ))} + + + - setPhysics({ ...physics, nodeRel: value })} - /> - {threeDim && ( - <> - setPhysics({ ...physics, nodeOpacity: value })} - /> - setPhysics({ ...physics, nodeResolution: value })} - /> - - )} - setPhysics({ ...physics, linkWidth: value })} - /> - {threeDim && ( + } + align="stretch" + paddingLeft={7} + color="gray.800" + > setPhysics({ ...physics, linkOpacity: value })} + label="Node size" + value={physics.nodeRel} + onChange={(value) => setPhysics({ ...physics, nodeRel: value })} /> - )} - - - Labels - - } - > - {!physics.labels - ? 'Never' - : physics.labels < 2 - ? 'On Highlight' - : 'Always'} - - - setPhysics({ ...physics, labels: 0 })}> - Never - - setPhysics({ ...physics, labels: 1 })}> - On Highlight - - setPhysics({ ...physics, labels: 2 })}> - Always - - - - - 1} animateOpacity> - + {threeDim && ( + <> setPhysics({ ...physics, labelScale: value / 5 })} + label="Node opacity" + value={physics.nodeOpacity} + min={0} + max={1} + onChange={(value) => setPhysics({ ...physics, nodeOpacity: value })} /> - - - - setPhysics({ ...physics, particles: !physics.particles })} - > - setPhysics({ ...physics, particlesNumber: value })} - /> + setPhysics({ ...physics, nodeResolution: value })} + /> + + )} setPhysics({ ...physics, particlesWidth: value })} + label="Link width" + value={physics.linkWidth} + onChange={(value) => setPhysics({ ...physics, linkWidth: value })} /> - - setPhysics({ ...physics, highlight: !physics.highlight })} - value={physics.highlight} - > - } - align="stretch" - paddingLeft={0} + {threeDim && ( + setPhysics({ ...physics, linkOpacity: value })} + /> + )} + + + Labels + + } + > + {!physics.labels + ? 'Never' + : physics.labels < 2 + ? 'On Highlight' + : 'Always'} + + + setPhysics({ ...physics, labels: 0 })}> + Never + + setPhysics({ ...physics, labels: 1 })}> + On Highlight + + setPhysics({ ...physics, labels: 2 })}> + Always + + + + + 1} animateOpacity> + + + setPhysics({ ...physics, labelScale: value / 5 }) + } + /> + + + + setPhysics({ ...physics, particles: !physics.particles })} > setPhysics({ ...physics, highlightLinkSize: value })} + label="Particle Number" + value={physics.particlesNumber} + max={5} + step={1} + onChange={(value) => setPhysics({ ...physics, particlesNumber: value })} /> setPhysics({ ...physics, highlightNodeSize: value })} + label="Particle Size" + value={physics.particlesWidth} + onChange={(value) => setPhysics({ ...physics, particlesWidth: value })} /> - {/* + + setPhysics({ ...physics, highlight: !physics.highlight })} + value={physics.highlight} + > + } + align="stretch" + paddingLeft={0} + > + + setPhysics({ ...physics, highlightLinkSize: value }) + } + /> + + setPhysics({ ...physics, highlightNodeSize: value }) + } + /> + {/* Highlight node color Highlight link color */} - { - setPhysics({ ...physics, highlightAnim: !physics.highlightAnim }) - }} - value={physics.highlightAnim} - > - setPhysics({ ...physics, animationSpeed: v })} - value={physics.animationSpeed} - infoText="Slower speed has a chance of being buggy" - min={50} - max={1000} - step={10} - /> - - {/* setPhysics({ ...physics, animationSpeed: v })} + value={physics.animationSpeed} + infoText="Slower speed has a chance of being buggy" + min={50} + max={1000} + step={10} + /> + + {/* setPhysics({ ...physics, algorithmName: { option } }), )} /> */} - - - + + + + diff --git a/pages/_app.tsx b/pages/_app.tsx index c2edb69..f8ff942 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -110,7 +110,6 @@ function SubApp(props: any) { const missingColor = d3int.interpolate(emacsTheme.base1, emacsTheme.base2)(0.2) const borderColor = getBorderColor() const theme = useMemo(() => { - console.log('ii') return { colors: { white: emacsTheme.bg, @@ -171,6 +170,8 @@ function SubApp(props: any) { }, ghost: { color: highlightColor + '.500', + _hover: { bg: `inherit`, border: '1px solid', borderColor: highlightColor + '.500' }, + _active: { color: `inherit`, bg: highlightColor + '.500' }, }, }, }, diff --git a/pages/index.tsx b/pages/index.tsx index caf216c..bb801a4 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -133,13 +133,10 @@ export function GraphPage() { console.log(typeof message.type) switch (message.type) { case 'graphdata': - console.log('hey') parseGraphData(message.data) break case 'theme': console.log('Received theme data') - console.log(message.data) - console.log(setEmacsTheme) setEmacsTheme(message.data) break case 'command': @@ -157,7 +154,6 @@ export function GraphPage() { ].map((nodeId) => [nodeId, {}]), ) /* zoomToFit(500, 200, (node: OrgRoamNode)=>nodes[node.id!]) */ - console.log(nodes) } default: console.log('oopsie whoopsie') @@ -437,6 +433,35 @@ export const Graph = function (props: GraphProps) { [theme], ) + const highlightColors = useMemo(() => { + const allColors = [].concat( + visuals.nodeColorScheme /* && visuals.nodeColorScheme.map((c) => theme.colors[c][500])) */ || + [], + visuals.linkColorScheme /* && theme.colors.gray[visuals.linkColorScheme])]] */ || [], + visuals.linkHighlight /* && theme.colors[visuals.linkHighlight][500]) */ || [], + visuals.nodeHighlight /* && theme.colors[visuals.linkHighlight][500]) */ || [], + ) + + console.log(visuals.linkColorScheme) + const getColor = (c) => (isNaN(c) ? theme.colors[c][500] : theme.colors.gray[c]) + const highlightColors = Object.fromEntries( + allColors.map((color) => { + const color1 = getColor(color) + const crisscross = allColors.map((color2) => [ + color2, + d3int.interpolate(color1, getColor(color2)), + ]) + return [color, Object.fromEntries(crisscross)] + }), + ) + console.log(highlightColors) + return highlightColors + }, [ + visuals.nodeColorScheme, + visuals.linkHighlight, + visuals.nodeHighlight, + visuals.linkColorScheme, + ]) const highlightedLinks = useMemo(() => linksByNodeId[hoverNode?.id!] ?? [], [hoverNode]) const previouslyHighlightedLinks = useMemo( @@ -455,11 +480,67 @@ export const Graph = function (props: GraphProps) { [hoverNode, previouslyHighlightedLinks, lastHoverNode], ) + const getNodeColorById = (id: string) => { + const linklen = linksByNodeId[id!]?.length ?? 0 + const parentCiteNeighbors = linklen + ? linksByNodeId[id!]?.filter((link) => link.type === 'parent' || link.type === 'cite').length + : 0 + const neighbors = filter.parents ? linklen : linklen - parentCiteNeighbors! + + return visuals.nodeColorScheme[ + numbereWithinRange(neighbors, 0, visuals.nodeColorScheme.length - 1) + ] + } + const getLinkNodeColor = (link: OrgRoamLinkObject) => + linksByNodeId[link.target.id!]?.length < linksByNodeId[link.source.id!]?.length + ? getNodeColorById(link.target.id!) + : getNodeColorById(link.source.id!) + + const getLinkColor = (link: OrgRoamLinkObject) => { + // I'm so sorry + const linkIsHighlighted = isLinkRelatedToNode(link, centralHighlightedNode) + const linkWasHighlighted = isLinkRelatedToNode(link, lastHoverNode.current) + const needsHighlighting = linkIsHighlighted || linkWasHighlighted + // if we are matching the node color and don't have a highlight color + // or we don't have our own scheme and we're not being highlighted + if (!visuals.linkHighlight && !visuals.linkColorScheme && !needsHighlighting) { + const nodeColor = getLinkNodeColor(link) + return theme.colors[nodeColor][500] + } + if (!needsHighlighting && !visuals.linkColorScheme) { + const nodeColor = getLinkNodeColor(link) + return theme.colors[nodeColor][500] + } + if (!needsHighlighting && !visuals.linkColorScheme) { + const nodeColor = getLinkNodeColor(link) + return theme.colors[nodeColor][500] + } + if (!needsHighlighting) { + return theme.colors.gray[visuals.linkColorScheme] + } + + if (!visuals.linkHighlight && !visuals.linkColorScheme) { + const nodeColor = getLinkNodeColor(link) + return theme.colors[nodeColor][500] + } + if (!visuals.linkHighlight) { + return theme.colors.gray[visuals.linkColorScheme] + } + if (!visuals.linkColorScheme) { + return highlightColors[getLinkNodeColor(link)][visuals.linkHighlight](opacity) + } + return highlightColors[visuals.linkColorScheme][visuals.linkHighlight](opacity) + } + + const getLinkBaseColor = (link: OrgRoamLinkObject) => { + if (!visuals.linkColorScheme) { + } + } const graphCommonProps: ComponentPropsWithoutRef = { graphData: scopedGraphData, width: windowWidth, height: windowHeight, - backgroundColor: theme.white, + backgroundColor: theme.colors.gray[visuals.backgroundColor], nodeLabel: (node) => (node as OrgRoamNode).title, nodeColor: (node) => { if (!physics.colorful) { @@ -468,20 +549,9 @@ export const Graph = function (props: GraphProps) { : interGray(opacity) } if (node.id === emacsNodeId) { - return theme.colors['red'][500] + return theme.colors[visuals.emacsNodeColor][500] } - const palette = [ - 'pink', - 'purple', - 'blue', - 'cyan', - 'teal', - 'green', - 'yellow', - 'orange', - 'red', - ].filter((color) => !['red'].includes(color)) // otherwise links with parents get shown as having one note const linklen = linksByNodeId[node.id!]?.length ?? 0 const parentCiteNeighbors = linklen @@ -490,7 +560,11 @@ export const Graph = function (props: GraphProps) { : 0 const neighbors = filter.parents ? linklen : linklen - parentCiteNeighbors! - return theme.colors[palette[numbereWithinRange(neighbors, 0, palette.length - 1)]][500] + return theme.colors[ + visuals.nodeColorScheme[ + numbereWithinRange(neighbors, 0, visuals.nodeColorScheme.length - 1) + ] + ][500] }, nodeRelSize: physics.nodeRel, nodeVal: (node) => { @@ -570,11 +644,13 @@ export const Graph = function (props: GraphProps) { linkDirectionalParticles: physics.particles ? physics.particlesNumber : undefined, linkColor: (link) => { - const linkIsHighlighted = isLinkRelatedToNode(link, centralHighlightedNode) - const linkWasHighlighted = isLinkRelatedToNode(link, lastHoverNode.current) - return linkIsHighlighted || linkWasHighlighted - ? interHighlight(opacity) - : theme.colors.gray[500] + /* if (!physics.highlight || !visuals.linkHighlight) { + * return visuals.linkColorScheme + * ? theme.colors.gray[visuals.linkColorScheme] + * : theme.colors[getLinkNodeColor(link)][500] + * } */ + + return getLinkColor(link) }, linkWidth: (link) => { const linkIsHighlighted = isLinkRelatedToNode(link, centralHighlightedNode) -- cgit v1.2.3