Skip to content

Commit

Permalink
Move RowHeader, DragHandle with graph zoom
Browse files Browse the repository at this point in the history
Contributes: #71
  • Loading branch information
stephanzwicknagl committed Mar 27, 2024
1 parent 1f89687 commit 1d00efa
Show file tree
Hide file tree
Showing 13 changed files with 167 additions and 123 deletions.
4 changes: 1 addition & 3 deletions frontend/src/lib/components/Arrows.react.js
Expand Up @@ -9,9 +9,7 @@ import { v4 as uuidv4 } from 'uuid';
export function Arrows() {
const {highlightedSymbol} = useHighlightedSymbol();
const [arrows, setArrows] = React.useState([]);
const {
value: animationState,
} = useAnimationUpdater();
const {animationState} = useAnimationUpdater();

const calculateArrows = React.useCallback(() => {
return highlightedSymbol
Expand Down
59 changes: 59 additions & 0 deletions frontend/src/lib/components/DragHandle.react.js
@@ -0,0 +1,59 @@
import React, {Suspense} from 'react';
import './draghandle.css';
import PropTypes from 'prop-types';
import dragHandleRounded from '@iconify/icons-material-symbols/drag-handle-rounded';
import {IconWrapper} from '../LazyLoader';
import {AnimationUpdater} from '../contexts/AnimationUpdater';

export class DragHandle extends React.Component {
static contextType = AnimationUpdater;
constructor(props) {
super(props);
this.dragHandleRef = React.createRef();
}

componentDidMount() {
this.updateDragHandlePosition();
}

componentDidUpdate(prevState) {
if (
this.context.animationState?.graph_zoom !==
prevState.animationState?.graph_zoom
) {
this.updateDragHandlePosition();
}
}

updateDragHandlePosition() {
if (this.context.animationState?.graph_zoom) {
this.dragHandleRef.current.style.left = `${
-1 * this.context.animationState.graph_zoom.translation.x
}px`;
}
}

render() {
const {dragHandleProps} = this.props;
return (
<div
ref={this.dragHandleRef}
className="dragHandle"
{...dragHandleProps}
>
<Suspense fallback={<div>=</div>}>
<IconWrapper icon={dragHandleRounded} width="24" />
</Suspense>
</div>
);
}
}

DragHandle.propTypes = {
/**
* an object which should be spread as props on the HTML element to be used as the drag handle.
* The whole item will be draggable by the wrapped element.
**/
dragHandleProps: PropTypes.object,
};

22 changes: 13 additions & 9 deletions frontend/src/lib/components/Facts.react.js
Expand Up @@ -14,8 +14,8 @@ export function Facts() {
const opacityMultiplier = 0.8;
const branchSpaceRef = React.useRef(null);
const rowbodyRef = React.useRef(null);
const {animationUpdater} = useAnimationUpdater();
const animationUpdaterRef = React.useRef(animationUpdater);
const {setAnimationState} = useAnimationUpdater();
const setAnimationStateRef = React.useRef(setAnimationState);

React.useEffect(() => {
if (
Expand All @@ -36,14 +36,18 @@ export function Facts() {
}, [currentDragged, opacityMultiplier]);

const animateResize = React.useCallback(() => {
const animationUpdater = animationUpdaterRef.current;
const setAnimationState = setAnimationStateRef.current;
const element = rowbodyRef.current;
animationUpdater(-1, {
width: element.clientWidth,
height: element.clientHeight,
top: element.offsetTop,
left: element.offsetLeft,
});
setAnimationState((oldValue) => ({
...oldValue,
"-1": {
...oldValue["-1"],
width: element.clientWidth,
height: element.clientHeight,
top: element.offsetTop,
left: element.offsetLeft,
},
}));
}, []);
useResizeObserver(rowbodyRef, animateResize);

Expand Down
20 changes: 5 additions & 15 deletions frontend/src/lib/components/Node.react.js
Expand Up @@ -405,9 +405,8 @@ export function Node(props) {
const {dispatch: dispatchShownNodes} = useShownNodes();
const classNames = useHighlightedNodeToCreateClassName(node);
const [height, setHeight] = React.useState(emToPixel(minimumNodeHeight));
const {setValue, animationUpdater} = useAnimationUpdater();
const setValueRef = React.useRef(setValue);
const animationUpdaterRef = React.useRef(animationUpdater);
const {setAnimationState} = useAnimationUpdater();
const setAnimationStateRef = React.useRef(setAnimationState);
const {setShownDetail} = useShownDetail();
const dispatchShownNodesRef = React.useRef(dispatchShownNodes);
const nodeuuidRef = React.useRef(node.uuid);
Expand All @@ -426,11 +425,11 @@ export function Node(props) {
}, []);

React.useEffect(() => {
const setValue = setValueRef.current;
const setAnimationState = setAnimationStateRef.current;
const nodeuuid = nodeuuidRef.current;
setValue((oldValue) => ({...oldValue, [nodeuuid]: null}));
setAnimationState((oldValue) => ({...oldValue, [nodeuuid]: null}));
return () => {
setValue((v) => {
setAnimationState((v) => {
const {[nodeuuid]: _, ...rest} = v;
return rest;
});
Expand Down Expand Up @@ -460,15 +459,6 @@ export function Node(props) {
return (_) => window.removeEventListener('resize', checkForOverflow);
});

const animateResize = React.useCallback(() => {
const nodeuuid = nodeuuidRef.current;
const animationUpdater = animationUpdaterRef.current;
const element = animateHeightRef.current;
if (element === null) {return;}
animationUpdater(nodeuuid, {width: element.clientWidth, height: element.clientHeight, top: element.offsetTop, left: element.offsetLeft, isSubnode: isSubnode});
}, [isSubnode]);
// useResizeObserver(animateHeightRef, animateResize); // is this needed for good animation?

const divID = `${node.uuid}_animate_height`;

return (
Expand Down
103 changes: 48 additions & 55 deletions frontend/src/lib/components/Row.react.js
Expand Up @@ -11,42 +11,17 @@ import {
import {TRANSFORMATION, TRANSFORMATIONWRAPPER} from '../types/propTypes';
import {ColorPaletteContext} from '../contexts/ColorPalette';
import {useShownRecursion} from '../contexts/ShownRecursion';
import {IconWrapper} from '../LazyLoader';
import dragHandleRounded from '@iconify/icons-material-symbols/drag-handle-rounded';
import {make_default_nodes} from '../utils';
import useResizeObserver from '@react-hook/resize-observer';
import {
AnimationUpdater,
useAnimationUpdater,
} from '../contexts/AnimationUpdater';
import {DragHandle} from './DragHandle.react';

const animationIntervalInMs = 30;
const animationPickupThreshold = 0.01;

export class DragHandle extends React.Component {
constructor(props) {
super(props);
}
render() {
const {dragHandleProps} = this.props;
return (
<div className="dragHandle" {...dragHandleProps}>
<Suspense fallback={<div>=</div>}>
<IconWrapper icon={dragHandleRounded} width="24" />
</Suspense>
</div>
);
}
}

DragHandle.propTypes = {
/**
* an object which should be spread as props on the HTML element to be used as the drag handle.
* The whole item will be draggable by the wrapped element.
**/
dragHandleProps: PropTypes.object,
};

export class RowTemplate extends React.Component {
static contextType = TransformationContext;
constructor(props) {
Expand Down Expand Up @@ -94,12 +69,16 @@ export class RowTemplate extends React.Component {
if (element === null) {
return;
}
this.animationUpdater(this.props.item.id, {
width: element.clientWidth,
height: element.clientHeight,
top: element.offsetTop,
left: element.offsetLeft,
});
this.setAnimationState((oldValue) => ({
...oldValue,
[this.props.item.id]: {
...oldValue[this.props.item.id],
width: element.clientWidth,
height: element.clientHeight,
top: element.offsetTop,
left: element.offsetLeft,
},
}));
}, animationIntervalInMs);
}
if (this.props.itemSelected < animationPickupThreshold && this.intervalId !== null) {
Expand All @@ -114,17 +93,20 @@ export class RowTemplate extends React.Component {

return (
<AnimationUpdater.Consumer>
{({animationUpdater}) => {
this.animationUpdater = animationUpdater;
{({setAnimationState}) => {
this.setAnimationState = setAnimationState;
return (
<TransformationContext.Consumer>
{({state: {canDrop}}) => {
return (
<ColorPaletteContext.Consumer>
{({rowShading}) => {
const scaleConstant = 0.01;
const scaleConstant = 0.005;
const shadowConstant = 15;
const opacityMultiplier = 0.8;
const scale =
itemSelected * scaleConstant +
1;
const shadow =
itemSelected * shadowConstant +
0;
Expand All @@ -140,6 +122,8 @@ export class RowTemplate extends React.Component {
const containerStyle = {
position: 'relative',
maxHeight: '100%',
transform: `scale(${scale})`,
transformOrigin: 'left',
boxShadow: `rgba(0, 0, 0, 0.3) 0px ${shadow}px ${
2 * shadow
}px 0px`,
Expand Down Expand Up @@ -223,9 +207,8 @@ export function Row(props) {
const handleRef = useRef(null);
const [shownRecursion, ,] = useShownRecursion();
const transformationIdRef = useRef(transformation.id);
const {setValue, animationUpdater} = useAnimationUpdater();
const setValueRef = useRef(setValue);
const animationUpdaterRef = useRef(animationUpdater);
const {setAnimationState} = useAnimationUpdater();
const setAnimationStateRef = useRef(setAnimationState);

React.useEffect(() => {
if (headerRef.current && handleRef.current) {
Expand All @@ -235,11 +218,14 @@ export function Row(props) {
}, []);

React.useEffect(() => {
const setValue = setValueRef.current;
const setAnimationState = setAnimationStateRef.current;
const transformationId = transformationIdRef.current;
setValue((oldValue) => ({...oldValue, [transformationId]: null}));
setAnimationState((oldValue) => ({
...oldValue,
[transformationId]: null,
}));
return () => {
setValue((v) => {
setAnimationState((v) => {
const {[transformationId]: _, ...rest} = v;
return rest;
});
Expand All @@ -257,14 +243,17 @@ export function Row(props) {

const animateResize = React.useCallback(() => {
const transformationId = transformationIdRef.current;
const animationUpdater = animationUpdaterRef.current;
const setAnimationState = setAnimationStateRef.current;
const element = rowbodyRef.current;
animationUpdater(transformationId, {
width: element.clientWidth,
height: element.clientHeight,
top: element.offsetTop,
left: element.offsetLeft,
});
setAnimationState((oldValue) => ({
[transformationId]: {
...oldValue[transformationId],
width: element.clientWidth,
height: element.clientHeight,
top: element.offsetTop,
left: element.offsetLeft,
},
}));
}, []);
useResizeObserver(rowbodyRef, animateResize);

Expand All @@ -282,14 +271,18 @@ export function Row(props) {

return (
<div className={`row_container ${transformation.hash}`}>
<RowHeader transformation={transformation.rules} />
{dragHandleProps === null ?
null :
<DragHandle dragHandleProps={dragHandleProps} ref={handleRef} />
{ transformation.rules.length === 0
? null
: <RowHeader transformation={transformation.rules} />
}
{
dragHandleProps === null
? null
: <DragHandle dragHandleProps={dragHandleProps} ref={handleRef} />
}
{!showNodes ?
null :
<div ref={rowbodyRef} className="row_row">
{ !showNodes
? null
: <div ref={rowbodyRef} className="row_row">
{nodes.map((child, index) => {
const space_multiplier = child.space_multiplier * 100;
if (
Expand Down
12 changes: 12 additions & 0 deletions frontend/src/lib/components/RowHeader.react.js
Expand Up @@ -6,8 +6,20 @@ import { useAnimationUpdater } from "../contexts/AnimationUpdater";
export function RowHeader(props) {
const { transformation } = props;
const colorPalette = useColorPalette();
const { animationState } = useAnimationUpdater();
const rowHeaderRef = React.useRef(null);

React.useEffect(() => {
if (animationState?.graph_zoom) {
rowHeaderRef.current.style.left = `${
-1 * animationState.graph_zoom.translation.x
}px`;
}
}, [animationState.graph_zoom]);

return (
<div
ref={rowHeaderRef}
style={{
backgroundColor: colorPalette.primary,
color: colorPalette.light,
Expand Down
14 changes: 14 additions & 0 deletions frontend/src/lib/components/draghandle.css
@@ -0,0 +1,14 @@
.dragHandle {
visibility: hidden;
cursor: move;
padding-left: 10px;
width: 20px;
height: 16px;
position: absolute;
z-index: 8;
margin-top: -5px;
}

.row_container:hover .dragHandle {
visibility: visible;
}
10 changes: 0 additions & 10 deletions frontend/src/lib/components/row.css
Expand Up @@ -59,13 +59,3 @@
filter: grayscale(100%);

}
.dragHandle {
visibility: hidden;
cursor: move;
padding-left: 10px;
width: 20px;
height: 16px;
}
.row_container:hover .dragHandle{
visibility: visible;
}

0 comments on commit 1d00efa

Please sign in to comment.