ViewModel.java |
1 /**************************************************************************** 2 * This demo file is part of yFiles for Java 2.14. 3 * Copyright (c) 2000-2017 by yWorks GmbH, Vor dem Kreuzberg 28, 4 * 72070 Tuebingen, Germany. All rights reserved. 5 * 6 * yFiles demo files exhibit yFiles for Java functionalities. Any redistribution 7 * of demo files in source code or binary form, with or without 8 * modification, is not permitted. 9 * 10 * Owners of a valid software license for a yFiles for Java version that this 11 * demo is shipped with are allowed to use the demo source code as basis 12 * for their own yFiles for Java powered applications. Use of such programs is 13 * governed by the rights and conditions as set out in the yFiles for Java 14 * license agreement. 15 * 16 * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 19 * NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 21 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 23 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 24 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * 27 ***************************************************************************/ 28 package demo.view.mindmap; 29 30 import y.base.Edge; 31 import y.base.EdgeList; 32 import y.base.EdgeMap; 33 import y.base.Node; 34 import y.base.NodeMap; 35 import y.view.Graph2D; 36 37 import java.util.Collection; 38 import java.util.Iterator; 39 import java.util.LinkedHashSet; 40 41 /** 42 * Provides methods to determine the mind map root item, 43 * cross-reference connections, the collapsed state of items, as well as the 44 * location of items relative to the root item. 45 * Additionally, items that are temporarily removed from the mind map 46 * are stored here, too. 47 */ 48 public class ViewModel { 49 /** 50 * Singleton instance of the view model. 51 */ 52 public static final ViewModel instance = new ViewModel(); 53 54 55 /** 56 * The data structure that represents the mind map. 57 */ 58 public final Graph2D graph; 59 60 /** 61 * Stores a mapping from collapsed node to the corresponding hidden, 62 * non-cross-reference edges. 63 * <p> 64 * Note, edges that are removed from a graph still reference their source and 65 * target nodes, which means that hidden nodes are stored implicitly as well. 66 * </p> 67 */ 68 private final NodeMap hiddenEdges; 69 /** 70 * Determines which nodes are placed to the left and to the right of the root 71 * node. 72 */ 73 private final NodeMap leftOrRight; 74 /** 75 * Determines which edges represent cross-references. 76 */ 77 private final EdgeMap crossReferences; 78 /** 79 * Stores hidden cross-reference edges. 80 */ 81 private final Collection hiddenCrossReferences; 82 83 /** 84 * The root node of the mind map. 85 */ 86 private Node root; 87 88 private ViewModel() { 89 graph = new Graph2D(); 90 hiddenEdges = graph.createNodeMap(); 91 leftOrRight = graph.createNodeMap(); 92 LayoutUtil.addLeftRightMap(graph, leftOrRight); 93 crossReferences = graph.createEdgeMap(); 94 LayoutUtil.addCrossReferencesMap(graph, crossReferences); 95 hiddenCrossReferences = new LinkedHashSet(); 96 97 LayoutUtil.addPlacersAndComparators(graph); 98 } 99 100 101 /** 102 * Determines if the specified node represents the root item of the mind map. 103 * @param node the node to be checked. 104 * @return <code>true</code> if the specified node represents the root item 105 * of the mind map; <code>false</code> otherwise. 106 */ 107 public boolean isRoot( final Node node ) { 108 return node == root; 109 } 110 111 /** 112 * Returns the root node of the mind map. 113 * @return the root node of the mind map. 114 */ 115 public Node getRoot() { 116 return root; 117 } 118 119 /** 120 * Sets the root node of the mind map. 121 * @param root the root node of the mind map. 122 */ 123 public void setRoot( final Node root ) { 124 this.root = root; 125 } 126 127 /** 128 * Determines if the specified node is currently collapsed in the mind map. 129 * @param node the node to be checked. 130 * @return <code>true</code> if the specified node is currently collapsed in 131 * the mind map; <code>false</code> otherwise. 132 */ 133 public boolean isCollapsed( final Node node ) { 134 final EdgeList edges = getHiddenEdges(node); 135 return edges != null && !edges.isEmpty(); 136 } 137 138 /** 139 * Determines if the given node should be placed to the left or to the right 140 * of the root node. 141 * @param node the node whose relative placement is required. 142 * @return <code>true</code> if the node should be placed to the left of the 143 * root node; <code>false</code> otherwise. 144 */ 145 public boolean isLeft( final Node node ) { 146 return leftOrRight.getBool(node); 147 } 148 149 /** 150 * Specifies if the given node should be placed to the left or to the right 151 * of the root node. 152 * @param node the node whose placement is specified. 153 * @param left if <code>true</code>, the node is placed to the left of the 154 * root node, otherwise it is placed to the right of the root node. 155 */ 156 public void setLeft( final Node node, final boolean left ) { 157 leftOrRight.setBool(node, left); 158 } 159 160 /** 161 * Retrieves and removes the non-cross-reference edges that were temporarily 162 * removed from the mind map when the specified node was collapsed. 163 * Note, the returned list implicitly specifies the subtree to re-insert 164 * into the mind map when expanding the specified node because removed edges 165 * still reference their original source and target nodes. 166 * @param node a currently collapsed node. 167 * @return an {@link EdgeList} with all non-cross-reference edges that were 168 * temporarily removed when the specified node was collapsed or 169 * <code>null</code> if there are no temporarily removed edges for the 170 * specified node. 171 * @see #setHiddenEdges(y.base.Node, y.base.EdgeList) 172 */ 173 public EdgeList popHiddenEdges( final Node node ) { 174 final EdgeList edges = getHiddenEdges(node); 175 hiddenEdges.set(node, null); 176 return edges; 177 } 178 179 /** 180 * Stores the non-cross-reference edges that were temporarily removed from 181 * the mind map when the specified node was collapsed. 182 * Note, the specified list has to include all edges in the subtree rooted at 183 * the specified node at the time of collapsing. 184 * @param node the node that is collapsed. 185 * @param edges a list of temporarily removed non-cross-reference edges. 186 * @see #popHiddenEdges(y.base.Node) 187 */ 188 public void setHiddenEdges( final Node node, final EdgeList edges ) { 189 hiddenEdges.set(node, edges); 190 } 191 192 /** 193 * Returns the currently hidden, non-cross-reference edges that define 194 * the subtree rooted at the specified node. 195 * @param node a currently collapsed node. 196 * @return an {@link EdgeList} with all the non-cross-reference edges that 197 * define the subtree rooted at the specified node. 198 */ 199 private EdgeList getHiddenEdges( final Node node ) { 200 return (EdgeList) hiddenEdges.get(node); 201 } 202 203 204 /** 205 * Determines if the specified edge is a cross-reference in the mind map. 206 * @param edge the edge to check. 207 * @return <code>true</code> if the specified edge is a cross-reference in 208 * the min map; <code>false</code> otherwise. 209 * @see #setCrossReference(y.base.Edge) 210 */ 211 public boolean isCrossReference( final Edge edge ) { 212 return crossReferences.getBool(edge); 213 } 214 215 /** 216 * Marks the specified edge as a cross-reference in the mind map. 217 * @param edge the edge to mark as cross-reference. 218 * @see #isCrossReference(y.base.Edge) 219 */ 220 public void setCrossReference( final Edge edge ) { 221 crossReferences.setBool(edge, true); 222 } 223 224 /** 225 * Stores the specified, temporarily removed cross-reference edges for 226 * later reinsertion. 227 * @param edges a list of temporarily removed cross-reference edges. 228 * @see #hiddenCrossReferences() 229 * @see #clearHiddenCrossReferences() 230 */ 231 public void addHiddenCrossReferences( final Collection edges ) { 232 hiddenCrossReferences.addAll(edges); 233 } 234 235 /** 236 * Iterates over the temporarily removed cross-reference edges. 237 * @return an {@link Iterator} for the temporarily removed cross-reference 238 * edges. 239 */ 240 public Iterator hiddenCrossReferences() { 241 return hiddenCrossReferences.iterator(); 242 } 243 244 /** 245 * Clears the cache of temporarily removed cross-reference edges. 246 * @see #addHiddenCrossReferences(java.util.Collection) 247 */ 248 public void clearHiddenCrossReferences() { 249 hiddenCrossReferences.clear(); 250 } 251 } 252