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.graphexplorer;
29  
30  import y.base.Edge;
31  import y.base.Node;
32  import y.view.Graph2D;
33  import y.view.Graph2DView;
34  
35  import java.util.HashSet;
36  import java.util.Iterator;
37  import java.util.LinkedHashSet;
38  import java.util.Set;
39  
40  /**
41   * Encapsulates information about old/removed and new elements for
42   * partial/incremental and complete re-layout.
43   *
44   */
45  final class LayoutContext {
46    private final Graph2DView view;
47    private final boolean animated;
48    private final boolean fromSketch;
49    private final Node fixedNode;
50    private boolean groupingMode ;
51    private final Set newNodes;
52    private final Set newEdges;
53    private final Set oldNodes;
54    private final Set oldEdges;
55    private final Set removedNodes;
56    private final Set removedEdges;
57  
58    /**
59     * Initializes a new context object for the specified view.
60     * @param view the view whose associated graph is laid out.
61     * @param animated if <code>true</code> the calculated layout will be applied
62     * in an animated fashion.
63     * @param fromSketch if <code>true</code> an incremental layout should be
64     * calculated.
65     * @param fixedNode specifies a node whose coordinates may not change.
66     * @param groupingMode specifies a node whose coordinates may not change.
67     */
68    LayoutContext(
69            final Graph2DView view,
70            final boolean animated,
71            final boolean fromSketch,
72            final Node fixedNode,
73            final boolean groupingMode
74    ) {
75      this.view = view;
76      this.animated = animated;
77      this.fromSketch = fromSketch;
78      this.fixedNode = fixedNode;
79      this.groupingMode = groupingMode;
80      this.newNodes = new LinkedHashSet();
81      this.newEdges = new LinkedHashSet();
82      this.oldNodes = new HashSet();
83      this.oldEdges = new HashSet();
84      this.removedNodes = new LinkedHashSet();
85      this.removedEdges = new LinkedHashSet();
86      this.groupingMode = groupingMode;
87    }
88  
89    /**
90     * Returns the view whose graph is laid out.
91     * @return the view whose graph is laid out.
92     */
93    Graph2DView getView() {
94      return view;
95    }
96  
97    /**
98     * Returns the graph that is laid out.
99     * @return the graph that is laid out.
100    */
101   Graph2D getGraph2D() {
102     return view.getGraph2D();
103   }
104 
105   /**
106    * Returns a node whose coordinates may not change.
107    * @return a node whose coordinates may not change.
108    */
109   Node getFixedNode() {
110     return fixedNode;
111   }
112 
113   /**
114    * Determines whether or not the calculated layout should be applied in an
115    * animated fashion.
116    * @return <code>true</code> if the calculated layout should be applied in an
117    * animated fashion; <code>false</code> otherwise.
118    */
119   public boolean isAnimated() {
120     return animated;
121   }
122 
123   /**
124    * Determines whether or not an incremental layout should be calculated.
125    * @return <code>true</code> if an incremental layout should be calculated;
126    * <code>false</code> otherwise.
127    */
128   boolean isFromSketch() {
129     return fromSketch;
130   }
131 
132   /**
133    * Marks a node as <em>new</em> for the purpose of layout calculation.
134    * <p>
135    * New nodes are laid out in an optimal way when performing an incremental
136    * layout calculation.
137    * </p>
138    * @param node the node to mark as new.
139    * @see #newNodes()
140    * @see #isNewNode(y.base.Node)
141    */
142   void addNewNode( final Node node ) {
143     newNodes.add(node);
144   }
145 
146   /**
147    * Returns an iterator over all nodes marked as <em>new</code>.
148    * <p>
149    * New nodes are laid out in an optimal way when performing an incremental
150    * layout calculation.
151    * </p>
152    * @return an iterator over all nodes marked as <em>new</code>.
153    * @see #addNewNode(y.base.Node)
154    * @see #isNewNode(y.base.Node)
155    */
156   Iterator newNodes() {
157     return newNodes.iterator();
158   }
159 
160   /**
161    * Returns whether or not the specified node is marked as <em>new</em>.
162    * <p>
163    * New nodes are laid out in an optimal way when performing an incremental
164    * layout calculation.
165    * </p>
166    * @param node the node to check.
167    * @return <code>true</code> if the specified node is marked as <em>new</em>;
168    * <code>false</code> otherwise.
169    * @see #addNewNode(y.base.Node)
170    * @see #newNodes()
171    */
172   boolean isNewNode( final Node node ) {
173     return newNodes.contains(node);
174   }
175 
176   /**
177    * Marks an edge as <em>new</em> for the purpose of layout calculation.
178    * <p>
179    * New edges are laid out in an optimal way when performing an incremental
180    * layout calculation.
181    * </p>
182    * @param edge the edge to mark as new.
183    * @see #newEdges()
184    */
185   void addNewEdge( final Edge edge ) {
186     newEdges.add(edge);
187   }
188 
189   /**
190    * Returns an iterator over all edges marked as <em>new</code>.
191    * <p>
192    * New edges are laid out in an optimal way when performing an incremental
193    * layout calculation.
194    * </p>
195    * @return an iterator over all edges marked as <em>new</code>.
196    * @see #addNewEdge(y.base.Edge)
197    */
198   Iterator newEdges() {
199     return newEdges.iterator();
200   }
201 
202   /**
203    * Returns whether or not the specified edge is marked as <em>new</em>.
204    * <p>
205    * New edges are laid out in an optimal way when performing an incremental
206    * layout calculation.
207    * </p>
208    * @param edge the edge to check.
209    * @return <code>true</code> if the specified edge is marked as <em>new</em>;
210    * <code>false</code> otherwise.
211    * @see #addNewEdge(y.base.Edge)
212    * @see #newEdges()
213    */
214   boolean isNewEdge( final Edge edge ) {
215     return newEdges.contains(edge);
216   }
217 
218 
219   /**
220    * Marks a node as <em>old</em> for the purpose of layout calculation.
221    * <p>
222    * If possible, old nodes are not changed when performing an incremental
223    * layout calculation.
224    * </p>
225    * @param node the node to mark as old.
226    * @see #isOldNode(y.base.Node)
227    */
228   void addOldNode( final Node node ) {
229     oldNodes.add(node);
230   }
231 
232   /**
233    * Returns whether or not the specified node is marked as <em>old</em>.
234    * <p>
235    * If possible, old nodes are not changed when performing an incremental
236    * layout calculation.
237    * </p>
238    * @param node the node to check.
239    * @return <code>true</code> if the specified node is marked as <em>old</em>;
240    * <code>false</code> otherwise.
241    * @see #addOldNode(y.base.Node)
242    */
243   boolean isOldNode( final Node node ) {
244     return oldNodes.contains(node);
245   }
246 
247   /**
248    * Marks an edge as <em>old</em> for the purpose of layout calculation.
249    * <p>
250    * If possible, old edges are not changed when performing an incremental
251    * layout calculation.
252    * </p>
253    * @param edge the edge to mark as old.
254    * @see #isOldEdge(y.base.Edge)
255    */
256   void addOldEdge( final Edge edge ) {
257     oldEdges.add(edge);
258   }
259 
260   /**
261    * Returns whether or not the specified edge is marked as <em>old</em>.
262    * <p>
263    * If possible, old edges are not changed when performing an incremental
264    * layout calculation.
265    * </p>
266    * @param edge the edge to check.
267    * @return <code>true</code> if the specified edge is marked as <em>old</em>;
268    * <code>false</code> otherwise.
269    * @see #addOldEdge(y.base.Edge)
270    */
271   boolean isOldEdge( final Edge edge ) {
272     return oldEdges.contains(edge);
273   }
274 
275 
276   /**
277    * Marks a node for removal after layout calculation.
278    * <p>
279    * Nodes marked for removal are ignored when performing layout calculation
280    * and are faded out during layout change animation.
281    * </p>
282    * @param node the node to mark for removal.
283    * @see #removedNodes()
284    * @see #isRemovedNode(y.base.Node)
285    */
286   void addRemovedNode( final Node node ) {
287     removedNodes.add(node);
288   }
289 
290   /**
291    * Returns an iterator over all nodes marked for removal.
292    * <p>
293    * Nodes marked for removal are ignored when performing layout calculation
294    * and are faded out during layout change animation.
295    * </p>
296    * @return an iterator over all nodes marked for removal.
297    * @see #addRemovedNode(y.base.Node)
298    * @see #isRemovedNode(y.base.Node)
299    */
300   Iterator removedNodes() {
301     return removedNodes.iterator();
302   }
303 
304   /**
305    * Returns whether or not the specified node is marked for removal.
306    * <p>
307    * Nodes marked for removal are ignored when performing layout calculation
308    * and are faded out during layout change animation.
309    * </p>
310    * @param node the node to check.
311    * @return <code>true</code> if the specified node is marked for removal;
312    * <code>false</code> otherwise.
313    * @see #addRemovedNode(y.base.Node)
314    * @see #removedNodes()
315    */
316   boolean isRemovedNode( final Node node ) {
317     return removedNodes.contains(node);
318   }
319 
320   /**
321    * Marks an edge for removal after layout calculation.
322    * <p>
323    * Edges marked for removal are ignored when performing layout calculation
324    * and are faded out during layout change animation.
325    * </p>
326    * @param edge the edge to mark for removal.
327    * @see #removedEdges()
328    * @see #isRemovedEdge(y.base.Edge)
329    */
330   void addRemovedEdge( final Edge edge ) {
331     removedEdges.add(edge);
332   }
333 
334   /**
335    * Returns an iterator over all edges marked for removal.
336    * <p>
337    * Edges marked for removal are ignored when performing layout calculation
338    * and are faded out during layout change animation.
339    * </p>
340    * @return an iterator over all edges marked for removal.
341    * @see #addRemovedEdge(y.base.Edge)
342    * @see #isRemovedEdge(y.base.Edge)
343    */
344   Iterator removedEdges() {
345     return removedEdges.iterator();
346   }
347 
348   /**
349    * Returns whether or not the specified edge is marked for removal.
350    * <p>
351    * Edge marked for removal are ignored when performing layout calculation
352    * and are faded out during layout change animation.
353    * </p>
354    * @param edge the edge to check.
355    * @return <code>true</code> if the specified edge is marked for removal;
356    * <code>false</code> otherwise.
357    * @see #addRemovedEdge(y.base.Edge)
358    * @see #removedEdges()
359    */
360   boolean isRemovedEdge( final Edge edge ) {
361     return removedEdges.contains(edge);
362   }
363 
364   /**
365    * Signals whether or not a layout algorithm shall treat the layout graph as
366    * being grouped.
367    * @return <code>true</code> if a layout algorithm shall treat the layout
368    * graph as being grouped; <code>false</code> otherwise.
369    */
370   public boolean isGroupingMode() {
371     return groupingMode;
372   }
373 }
374