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.networkmonitoring;
29  
30  import demo.view.DemoBase;
31  import y.anim.AnimationObject;
32  import y.anim.AnimationPlayer;
33  import y.base.DataMap;
34  import y.util.DefaultMutableValue2D;
35  import y.util.Maps;
36  import y.view.BackgroundRenderer;
37  import y.view.DefaultGraph2DRenderer;
38  import y.view.EditMode;
39  import y.view.NavigationMode;
40  import y.view.ViewAnimationFactory;
41  import y.view.YRenderingHints;
42  
43  import javax.swing.AbstractAction;
44  import javax.swing.Action;
45  import javax.swing.JToolBar;
46  import javax.swing.Timer;
47  import java.awt.Color;
48  import java.awt.Dimension;
49  import java.awt.EventQueue;
50  import java.awt.GradientPaint;
51  import java.awt.Graphics2D;
52  import java.awt.Paint;
53  import java.awt.Rectangle;
54  import java.awt.event.ActionEvent;
55  import java.awt.event.ActionListener;
56  import java.beans.PropertyChangeEvent;
57  import java.beans.PropertyChangeListener;
58  import java.util.Locale;
59  
60  /**
61   * This demo shows a simple network monitoring tool. You can watch the traffic flow through the network
62   * and even influence the network.
63   * The network consists of PCs, Laptops, Tablets, Switches, Servers, Databases and W-LANS. The color of the edges
64   * change from green to yellow to red depending on its traffic load. The traffic load of nodes is shown on their
65   * info label. Active edges are marked through an animation.
66   *
67   * Things to try
68   * <ul>
69   * <li>Open/Hide Info Label: Every node has an info label. It can be shown and hidden by clicking on the node. It shows
70   * the name, IP address and traffic load. You can also close it by clicking on the x in the top right corner.
71   * Remember that info labels are only visible at a detailed zoom level.</li>
72   * <li>Disable nodes: The info label also contains a power button in the bottom right corner. Clicking on it
73   * (de)activates the node, preventing it from processing data. This way you can influence the data flow and watch
74   * what happens.</li>
75   * <li>Enable Failures: By Clicking on "Enable Failures" you allow failures to happen randomly. Nodes and edges get
76   * broken and can't process data anymore. Broken elements are marked with a stop sign. If a failure happens on a node
77   * or edge outside the current viewport, then the viewport will be moved to focus the broken element.
78   * You can repair elements by clicking on the stop sign. To repair a node, you can also
79   * open the info label and then click on the green arc arrow at the bottom right corner.</li>
80   * </ul>
81   */
82  public class NetworkMonitoringDemo extends DemoBase {
83    static final double MAX_ZOOM = 3;
84    static final double MIN_ZOOM = 0.15;
85    static final double PAINT_DETAIL_THRESHOLD = 0.25;
86    static final double LABEL_HIDE_ZOOM_LEVEL = 0.55;
87  
88    private NetworkModel model;
89    private DataMap view2model;
90  
91    public NetworkMonitoringDemo() {
92      this(null);
93    }
94  
95    public NetworkMonitoringDemo(final String helpFilePath) {
96      addHelpPane(helpFilePath);
97      // start with a bigger view than usual
98      view.setPreferredSize(new Dimension(1200, 900));
99  
100     final NetworkView networkView = new NetworkView(model, view, view2model);
101     model.addObserver(networkView);
102 
103     addBackgroundRenderer();
104     ((DefaultGraph2DRenderer) view.getGraph2DRenderer()).setDrawEdgesFirst(true);
105     addZoomThreshold();
106 
107     // initially zoom in to avoid sloppy view in the beginning
108     final Timer timer = new Timer(500, new ActionListener() {
109       public void actionPerformed(ActionEvent e) {
110         final ViewAnimationFactory factory = new ViewAnimationFactory(view);
111         final Rectangle graphBounds = view.getGraph2D().getBoundingBox();
112         final DefaultMutableValue2D newCenter =
113             DefaultMutableValue2D.create(graphBounds.getWidth() * 0.4, graphBounds.getHeight() * 0.4);
114         final AnimationObject focus = factory.focusView(0.5, newCenter, 1000);
115         final AnimationPlayer player = factory.createConfiguredPlayer();
116         player.animate(focus);
117       }
118     });
119     timer.setRepeats(false);
120     timer.start();
121   }
122 
123   /**
124    * Overwritten to make sure that the model and the model-view-mapping are initialized before
125    * {@link NetworkInteractionMode} is created and added to the view.
126    */
127   protected void initialize() {
128     view2model = Maps.createHashedDataMap();
129     model = new NetworkModelImpl(getResource("resource/network.graphml"));
130   }
131 
132   /**
133    * Adds a {@link BackgroundRenderer} that paints a gradient background to the view.
134    */
135   private void addBackgroundRenderer() {
136     view.setBackgroundRenderer(new BackgroundRenderer() {
137         public void paint(Graphics2D gfx, int x, int y, int w, int h) {
138           final Rectangle visibleRect = view.getVisibleRect();
139           //Store old paint
140           final Paint oldPaint = gfx.getPaint();
141           //Draw a rectangle in the visible area, using the GradientPainter.
142           GradientPaint gradientPaint = new GradientPaint(visibleRect.x, visibleRect.y, Color.WHITE,
143                         visibleRect.x + visibleRect.width, visibleRect.y + visibleRect.height, new Color(195, 211, 238));
144           gfx.setPaint(gradientPaint);
145           gfx.fillRect(visibleRect.x, visibleRect.y, visibleRect.width, visibleRect.height);
146           //Reset old paint
147           gfx.setPaint(oldPaint);
148         }
149       });
150   }
151 
152   /**
153    * Adds thresholds to paint different details of the graph depending on the zoom level.
154    */
155   private void addZoomThreshold() {
156     view.setPaintDetailThreshold(PAINT_DETAIL_THRESHOLD);
157     view.getCanvasComponent().addPropertyChangeListener(new PropertyChangeListener() {
158       public void propertyChange(PropertyChangeEvent evt) {
159         if (evt.getPropertyName().equals("Zoom")) {
160           final double zoom = ((Double) evt.getNewValue()).doubleValue();
161           if (zoom <= LABEL_HIDE_ZOOM_LEVEL) {
162             view.getRenderingHints().put(
163                 YRenderingHints.KEY_NODE_LABEL_PAINTING,
164                 YRenderingHints.VALUE_NODE_LABEL_PAINTING_OFF);
165           } else {
166             view.getRenderingHints().put(
167                 YRenderingHints.KEY_NODE_LABEL_PAINTING,
168                 YRenderingHints.VALUE_NODE_LABEL_PAINTING_ON);
169           }
170           if (zoom < MIN_ZOOM) {
171             view.setZoom(MIN_ZOOM);
172           } else if (zoom > MAX_ZOOM) {
173             view.setZoom(MAX_ZOOM);
174           }
175         }
176       }
177     });
178   }
179 
180   /**
181    * Overwritten because this demo is not editable.
182    */
183   protected EditMode createEditMode() {
184     return null;
185   }
186 
187   /**
188    * Overwritten to register {@link NavigationMode} and a custom view mode that provides possible interactions for this
189    * demo.
190    */
191   protected void registerViewModes() {
192     view.addViewMode(new NavigationMode());
193     view.addViewMode(new NetworkInteractionMode(model, view2model));
194   }
195 
196   /**
197    * Launches this demo.
198    */
199   public static void main(String[] args) {
200       EventQueue.invokeLater(new Runnable() {
201         public void run() {
202           Locale.setDefault(Locale.ENGLISH);
203           initLnF();
204           (new NetworkMonitoringDemo("resource/networkhelp.html")).start("Network Monitoring Demo");
205         }
206       });
207     }
208 
209   /**
210    * Overwritten to disable deletion of graph elements because this demo is not editable.
211    */
212   protected boolean isDeletionEnabled() {
213     return false;
214   }
215 
216   /**
217    * Overwritten to disable undo and redo because this demo is not editable.
218    */
219   protected boolean isUndoRedoEnabled() {
220     return false;
221   }
222 
223   /**
224    * Overwritten to disable clipboard because this demo is not editable.
225    */
226   protected boolean isClipboardEnabled() {
227     return false;
228   }
229 
230   /**
231    * Overwritten to disable loading a graph because this demo is not editable and should only use the initial graph.
232    */
233   protected Action createLoadAction() {
234     return null;
235   }
236 
237   /**
238    * Overwritten to disable saving a graph because this demo is not editable and the initial graph does not change.
239    */
240   protected Action createSaveAction() {
241     return null;
242   }
243 
244   /**
245    * Overwritten to customize the toolbar for this demo. A button is added to enable/disable failures in the network.
246    */
247   protected JToolBar createToolBar() {
248     final JToolBar toolBar = super.createToolBar();
249     toolBar.add(new AbstractAction("Enable Failures") {
250       public void actionPerformed(ActionEvent e) {
251         if (model.isNetworkErrorsEnabled()) {
252           putValue(Action.NAME,"Enable Failures");
253           model.setNetworkErrorsEnabled(false);
254         } else {
255           putValue(Action.NAME,"Disable Failures");
256           model.setNetworkErrorsEnabled(true);
257         }
258       }
259     });
260     return toolBar;
261   }
262 }
263