| 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