From 723768fa3707f124c906cd5bccf44728275be549 Mon Sep 17 00:00:00 2001 From: James Hadfield Date: Tue, 21 Sep 2021 16:26:34 +1200 Subject: [PATCH] [tree] button to go back to previous zoom The ability to return to the previous zoom level is useful when exploring trees in detail, especially when combined with the magnifying glass (which zooms out). A hover info box has been added to convey the functionality of this icon. The implementation involving multiple trees is conceptually more complicated, as I don't want us to return to the previous zoom state in each tree. (This is similar to the magnifiying glass icon, which zooms out in both trees.) The best solution is probably tree-specific UI. For now, this functionality is only surfaced if we are viewing a single tree. --- src/actions/tree.js | 24 +++++++++++++++++++++++- src/components/tree/tree.js | 34 +++++++++++++++++++++++++++++++++- src/reducers/tree.js | 4 ++++ 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/actions/tree.js b/src/actions/tree.js index 6518652de..77389a799 100644 --- a/src/actions/tree.js +++ b/src/actions/tree.js @@ -49,7 +49,7 @@ export const applyInViewNodesToTree = (idx, tree) => { * @return {function} a function to be handled by redux (thunk) */ export const updateVisibleTipsAndBranchThicknesses = ( - {root = [undefined, undefined], cladeSelected = undefined} = {} + {root = [undefined, undefined], cladeSelected = undefined, revertTreeZoom = false} = {} ) => { return (dispatch, getState) => { const { tree, treeToo, controls, frequencies } = getState(); @@ -61,6 +61,19 @@ export const updateVisibleTipsAndBranchThicknesses = ( if (!tree.nodes) {return;} // console.log("ROOT SETTING TO", root) /* mark nodes as "in view" as applicable */ + + if (revertTreeZoom) { + // NOTE: currently this functionality is only implemented for the main tree + // any implementation for two trees will have to consider the order of zoom operations across the trees + const len = tree.idxOfInViewRootNodeHistory.length; + if (len===0) { + console.error("Error trying to revert tree zoom with no history"); + return; + } + root[0] = tree.idxOfInViewRootNodeHistory[len-1]; + root[1] = undefined; + } + const rootIdxTree1 = applyInViewNodesToTree(root[0], tree); const data = calculateVisiblityAndBranchThickness( @@ -111,6 +124,15 @@ export const updateVisibleTipsAndBranchThicknesses = ( visibilityToo: dispatchObj.visibilityToo }); + /* update the history stack for zoom levels (if we are zooming) */ + if (tree.idxOfFilteredRoot !== dispatchObj.idxOfInViewRootNode) { + if (revertTreeZoom) { + dispatchObj.idxOfInViewRootNodeHistory = tree.idxOfInViewRootNodeHistory.slice(0, -1); + } else { + dispatchObj.idxOfInViewRootNodeHistory = [...tree.idxOfInViewRootNodeHistory, tree.idxOfInViewRootNode]; + } + } + /* D I S P A T C H */ dispatch(dispatchObj); updateEntropyVisibility(dispatch, getState); diff --git a/src/components/tree/tree.js b/src/components/tree/tree.js index d810c8cf1..061fe4fb9 100644 --- a/src/components/tree/tree.js +++ b/src/components/tree/tree.js @@ -1,6 +1,6 @@ import React from "react"; import { withTranslation } from "react-i18next"; -import { FaSearchMinus } from "react-icons/fa"; +import { FaSearchMinus, FaReply } from "react-icons/fa"; import { updateVisibleTipsAndBranchThicknesses } from "../../actions/tree"; import Card from "../framework/card"; import Legend from "./legend/legend"; @@ -10,6 +10,7 @@ import HoverInfoPanel from "./infoPanels/hover"; import TipClickedPanel from "./infoPanels/click"; import { changePhyloTreeViaPropsComparison } from "./reactD3Interface/change"; import * as callbacks from "./reactD3Interface/callbacks"; +import { StyledTooltip } from "../controls/styles"; import { tabSingle, darkGrey, lightGrey } from "../../globalStyles"; import { renderTree } from "./reactD3Interface/initialRender"; import Tangle from "./tangle"; @@ -109,6 +110,8 @@ class Tree extends React.Component { const treeIsZoomed = this.props.tree.idxOfInViewRootNode !== 0 || this.props.treeToo.idxOfInViewRootNode !== 0; + const treeCanReturnToPreviousZoom = !!this.props.tree.idxOfInViewRootNodeHistory.length; + return { treeButtonsDiv: { zIndex: 100, @@ -137,6 +140,17 @@ class Tree extends React.Component { color: treeIsZoomed ? darkGrey : lightGrey, pointerEvents: treeIsZoomed ? "auto" : "none", marginRight: "4px" + }, + revertTreeZoomButton: { + zIndex: 100, + display: "inline-block", + cursor: treeCanReturnToPreviousZoom ? "pointer" : "auto", + color: treeCanReturnToPreviousZoom ? darkGrey : lightGrey, + pointerEvents: treeCanReturnToPreviousZoom ? "auto" : "none", + marginRight: "4px" + }, + helpTooltip: { + textTransform: "none" } }; }; @@ -159,6 +173,10 @@ class Tree extends React.Component { })); }; + revertTreeZoom = () => { + this.props.dispatch(updateVisibleTipsAndBranchThicknesses({revertTreeZoom: true})); + } + zoomBack = () => { let newRoot, newRootToo; // Zoom out of main tree if index of root node is not 0 @@ -224,6 +242,20 @@ class Tree extends React.Component { } {this.props.narrativeMode ? null : (
+ { this.props.showTreeToo ? + null : + () + }