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.layout.multipage;
29  
30  import y.base.Edge;
31  import y.base.Node;
32  import y.base.NodeCursor;
33  import y.layout.tree.BalloonLayouter;
34  import y.view.Arrow;
35  import y.view.Graph2D;
36  import y.view.Graph2DView;
37  import y.view.LocalViewCreator;
38  import y.view.NodeRealizer;
39  import y.view.ShapeNodeRealizer;
40  
41  import java.awt.Color;
42  import java.awt.Dimension;
43  import java.awt.EventQueue;
44  import java.beans.PropertyChangeEvent;
45  import java.beans.PropertyChangeListener;
46  import java.util.Comparator;
47  import java.util.Iterator;
48  import java.util.TreeSet;
49  import javax.swing.BorderFactory;
50  
51  
52  /**
53   * Overview component that displays all referenced pages for a given page graph.
54   *
55   */
56  class MultiPageOverview extends Graph2DView {
57    MultiPageOverview(
58            final Graph2DView pageView,
59            final MultiPageGraph2DBuilder pageBuilder
60    ) {
61      setPreferredSize(new Dimension(200, 200));
62      setBorder(BorderFactory.createLineBorder(Color.GRAY));
63  
64      // disable sloppy painting to ensure that labels are always painted
65      // regardless of current zoom level
66      setPaintDetailThreshold(0);
67  
68      getGraph2D().getDefaultEdgeRealizer().setTargetArrow(Arrow.STANDARD);
69  
70      // the MultiPageOverviewCreator rebuilds this component's graph each
71      // time the graph of the specified page view is replaced with a new one
72      final MultiPageOverviewCreator creator =
73              new MultiPageOverviewCreator(pageView, this, pageBuilder);
74      pageView.addPropertyChangeListener("Graph2D", new PropertyChangeListener() {
75        public void propertyChange( final PropertyChangeEvent e ) {
76          EventQueue.invokeLater(new Runnable() {
77            public void run() {
78              creator.updateViewGraph();
79            }
80          });
81        }
82      });
83    }
84  
85    /**
86     * Creates a graph that displays all referenced pages for a given page graph. 
87     */
88    private static final class MultiPageOverviewCreator extends LocalViewCreator {
89      private static final Color PAGE_BACKGROUND = new Color(230, 230, 230);
90      private final Graph2DView source;
91      private final Graph2DView target;
92      private final MultiPageGraph2DBuilder pageBuilder;
93  
94      MultiPageOverviewCreator(
95              final Graph2DView source,
96              final Graph2DView target,
97              final MultiPageGraph2DBuilder pageBuilder
98      ) {
99        this.source = source;
100       this.target = target;
101       this.pageBuilder = pageBuilder;
102 
103       // layout algorithm to lay out the multi-page overview graph in a
104       // star-shaped fashion
105       final BalloonLayouter layouter = new BalloonLayouter();
106       layouter.setComparator(new Comparator() {
107         public int compare( final Object o1, final Object o2 ) {
108           final int i1 = ((Edge) o1).index();
109           final int i2 = ((Edge) o2).index();
110           if (i1 < i2) {
111             return 1;
112           } else if (i1 > i2) {
113             return -1;
114           } else {
115             return 0;
116           }
117         }
118       });
119       setLayouter(layouter);
120     }
121 
122     protected void buildViewGraph() {
123       final Graph2D model = getModel();
124       if (model.isEmpty()) {
125         return;
126       }
127 
128       // determine the page represented by the given page graph
129       // as well as all referenced pages
130       final TreeSet pageNos = new TreeSet();
131       int currentPageNo = -1;
132       for (NodeCursor nc = model.nodes(); nc.ok(); nc.next()) {
133         final Node node = nc.node();
134         final int refPageNo = pageBuilder.getReferencedPageNo(node);
135         if (refPageNo > -1) {
136           pageNos.add(new Integer(refPageNo));
137         }
138         if (currentPageNo < 0) {
139           currentPageNo = pageBuilder.getPageNo(node);
140         }
141       }
142 
143       // create nodes for all referenced pages
144       final Graph2D view = getViewGraph();
145       final ShapeNodeRealizer snr = new ShapeNodeRealizer();
146       snr.getLabel().setFontSize(18);
147       snr.setFillColor(PAGE_BACKGROUND);
148       snr.setSize(42, 60);
149       for (Iterator it = pageNos.iterator(); it.hasNext();) {
150         final NodeRealizer page = snr.createCopy();
151         final Integer next = (Integer) it.next();
152         page.setLabelText(Integer.toString(next.intValue() + 1));
153         view.createNode(page);
154       }
155 
156       // create a node for the current page
157       snr.setSize(56, 80);
158       final NodeRealizer currentPage = snr.createCopy();
159       if (currentPageNo > -1) {
160         currentPage.setLabelText(Integer.toString(currentPageNo + 1));
161       }
162 
163       // connect the current page to all referenced pages
164       final Node current = view.createNode(currentPage);
165       for (NodeCursor nc = view.nodes(); nc.ok(); nc.next()) {
166         final Node node = nc.node();
167         if (node != current) {
168           view.createEdge(current, node);
169         }
170       }
171     }
172 
173     public Graph2D getModel() {
174       return source.getGraph2D();
175     }
176 
177     public Graph2D getViewGraph() {
178       return target.getGraph2D();
179     }
180 
181     public Node getModelNode( final Node view ) {
182       return null;
183     }
184 
185     public Node getViewNode( final Node model ) {
186       return null;
187     }
188 
189     public Edge getModelEdge( final Edge view ) {
190       return null;
191     }
192 
193     public Edge getViewEdge( final Edge model ) {
194       return null;
195     }
196   }
197 }
198