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.layout.DiscreteNodeLabelModel;
32  import y.view.EdgeLabel;
33  import y.view.EdgeRealizer;
34  import y.view.GenericEdgeRealizer;
35  import y.view.GenericNodeRealizer;
36  import y.view.NodeLabel;
37  import y.view.NodeRealizer;
38  import y.view.SimpleUserDataHandler;
39  import y.view.SmartEdgeLabelModel;
40  import y.view.YLabel;
41  
42  import javax.swing.Icon;
43  import java.awt.Color;
44  import java.awt.Component;
45  import java.awt.Graphics;
46  import java.awt.Graphics2D;
47  import java.awt.Insets;
48  import java.awt.geom.GeneralPath;
49  import java.net.URL;
50  import java.util.Map;
51  
52  /**
53   * Factory class that provides realizer configurations for network nodes and connections.
54   * Also provides color constants and a warning icon.
55   */
56  public class NetworkMonitoringFactory {
57    private static final String CONFIGURATION_WORKSTATION = "demo.view.networkmonitoring.NetworkModelImpl.CONFIGURATION_WORKSTATION";
58    private static final String CONFIGURATION_LAPTOP = "demo.view.networkmonitoring.NetworkModelImpl.CONFIGURATION_LAPTOP";
59    private static final String CONFIGURATION_SMARTPHONE = "demo.view.networkmonitoring.NetworkModelImpl.CONFIGURATION_SMARTPHONE";
60    private static final String CONFIGURATION_SWITCH = "demo.view.networkmonitoring.NetworkModelImpl.CONFIGURATION_SWITCH";
61    private static final String CONFIGURATION_WLAN = "demo.view.networkmonitoring.NetworkModelImpl.CONFIGURATION_WLAN";
62    private static final String CONFIGURATION_DATABASE = "demo.view.networkmonitoring.NetworkModelImpl.CONFIGURATION_DATABASE";
63    private static final String CONFIGURATION_SERVER = "demo.view.networkmonitoring.NetworkModelImpl.CONFIGURATION_SERVER";
64    private static final String CONFIGURATION_CONNECTION = "demo.view.networkmonitoring.NetworkModelImpl.CONFIGURATION_CONNECTION";
65    private static final String CONFIGURATION_NODE_INFO_LABEL = "demo.view.networkmonitoring.NetworkModelImpl.CONFIGURATION_NODE_INFO_LABEL";
66  
67    static final Color COLOR_DISABLED = Color.GRAY;
68    static final Color COLOR_BROKEN = Color.DARK_GRAY;
69    static final Color COLOR_WORKLOAD_FULL = new Color(255, 51, 0);
70    static final Color COLOR_WORKLOAD_HALF = new Color(255, 204, 0);
71    static final Color COLOR_WORKLOAD_NONE = new Color(0, 153, 0);
72    static final Color COLOR_BACKGROUND_INFO_LABEL = new Color(113, 200, 255);
73    static final Icon WARNING_ICON = new WarningIcon(20);
74  
75    static final double SQRT_2 = Math.sqrt(2);
76  
77    static final String[] NODE_TYPES = {
78        "workstation",
79        "laptop",
80        "smartphone",
81        "switch",
82        "wlan",
83        "database",
84        "server"
85    };
86    static final String[] NODE_CONFIGURATIONS = {
87        CONFIGURATION_WORKSTATION,
88        CONFIGURATION_LAPTOP,
89        CONFIGURATION_SMARTPHONE,
90        CONFIGURATION_SWITCH,
91        CONFIGURATION_WLAN,
92        CONFIGURATION_DATABASE,
93        CONFIGURATION_SERVER
94    };
95  
96    static {
97      // register different types of configurations for network nodes
98      for (int i = 0; i < NODE_TYPES.length; i++) {
99        final GenericNodeRealizer.Factory nodeFactory = GenericNodeRealizer.getFactory();
100       Map configMap = nodeFactory.createDefaultConfigurationMap();
101       URL enabledImage = DemoBase.getResource(NetworkMonitoringDemo.class, "resource/" + NODE_TYPES[i] + "_on.png");
102       URL disableImage = DemoBase.getResource(NetworkMonitoringDemo.class, "resource/" + NODE_TYPES[i] + "_off.png");
103       NetworkNodePainter configuration = new NetworkNodePainter(enabledImage, disableImage);
104       configuration.setAlphaImageUsed(true);
105       configMap.put(GenericNodeRealizer.Painter.class, configuration);
106       configMap.put(GenericNodeRealizer.ContainsTest.class, configuration);
107       configMap.put(GenericNodeRealizer.UserDataHandler.class,
108           new SimpleUserDataHandler(SimpleUserDataHandler.EXCEPTION_ON_FAILURE));
109       nodeFactory.addConfiguration(NODE_CONFIGURATIONS[i], configMap);
110     }
111 
112     // register configuration for network connections
113     final GenericEdgeRealizer.Factory edgeConfigFactory = GenericEdgeRealizer.getFactory();
114     final Map edgeImplMap = edgeConfigFactory.createDefaultConfigurationMap();
115     edgeImplMap.put(GenericEdgeRealizer.Painter.class, new NetworkConnectionPainter());
116     edgeImplMap.put(GenericEdgeRealizer.UserDataHandler.class, new SimpleUserDataHandler(SimpleUserDataHandler.EXCEPTION_ON_FAILURE));
117     edgeConfigFactory.addConfiguration(CONFIGURATION_CONNECTION, edgeImplMap);
118 
119     // register configuration for info labels
120     final YLabel.Factory labelFactory = NodeLabel.getFactory();
121     final Map labelConfigMap = labelFactory.createDefaultConfigurationMap();
122     final NetworkInfoLabelPainter infoLabelPainter = new NetworkInfoLabelPainter();
123     labelConfigMap.put(YLabel.Painter.class, infoLabelPainter);
124     labelConfigMap.put(YLabel.Layout.class, infoLabelPainter);
125     labelFactory.addConfiguration(CONFIGURATION_NODE_INFO_LABEL, labelConfigMap);
126   }
127 
128   /**
129    * Creates a configured node realizer that represents a workstation.
130    */
131   public static NodeRealizer createWorkstation() {
132     final GenericNodeRealizer realizer = createNodeRealizer();
133     realizer.setConfiguration(CONFIGURATION_WORKSTATION);
134     return realizer;
135   }
136 
137   /**
138    * Creates a configured node realizer that represents a laptop.
139    */
140   public static NodeRealizer createLaptop() {
141     final GenericNodeRealizer realizer = createNodeRealizer();
142     realizer.setConfiguration(CONFIGURATION_LAPTOP);
143     return realizer;
144   }
145 
146   /**
147    * Creates a configured node realizer that represents a smartphone.
148    */
149   public static NodeRealizer createSmartphone() {
150     final GenericNodeRealizer realizer = createNodeRealizer();
151     realizer.setConfiguration(CONFIGURATION_SMARTPHONE);
152     return realizer;
153   }
154 
155   /**
156    * Creates a configured node realizer that represents a switch.
157    */
158   public static NodeRealizer createSwitch() {
159     final GenericNodeRealizer realizer = createNodeRealizer();
160     realizer.setConfiguration(CONFIGURATION_SWITCH);
161     return realizer;
162   }
163 
164   /**
165    * Creates a configured node realizer that represents a w-lan router.
166    */
167   public static NodeRealizer createWLan() {
168     final GenericNodeRealizer realizer = createNodeRealizer();
169     realizer.setConfiguration(CONFIGURATION_WLAN);
170     return realizer;
171   }
172 
173   /**
174    * Creates a configured node realizer that represents a database.
175    */
176   public static NodeRealizer createDatabase() {
177     final GenericNodeRealizer realizer = createNodeRealizer();
178     realizer.setConfiguration(CONFIGURATION_DATABASE);
179     return realizer;
180   }
181 
182   /**
183    * Creates a configured node realizer that represents a server.
184    */
185   public static NodeRealizer createServer() {
186     final GenericNodeRealizer realizer = createNodeRealizer();
187     realizer.setConfiguration(CONFIGURATION_SERVER);
188     return realizer;
189   }
190 
191   /**
192    * Creates a configured node realizer that represents a network node.
193    */
194   private static GenericNodeRealizer createNodeRealizer() {
195     final GenericNodeRealizer realizer = new GenericNodeRealizer();
196     realizer.setUserData(new NetworkData(0));
197     realizer.setSize(64, 64);
198 
199     final NodeLabel infoLabel = realizer.getLabel();
200     infoLabel.setText("text");
201     infoLabel.setAlignment(YLabel.ALIGN_LEFT);
202     infoLabel.setInsets(new Insets(5, 5, 5, 5));
203     infoLabel.setBackgroundColor(COLOR_BACKGROUND_INFO_LABEL);
204     final DiscreteNodeLabelModel model = new DiscreteNodeLabelModel(DiscreteNodeLabelModel.EIGHT_POS_MASK);
205     model.setDistance(20);
206     infoLabel.setLabelModel(model, model.getDefaultParameter());
207     infoLabel.setConfiguration(CONFIGURATION_NODE_INFO_LABEL);
208     infoLabel.setVisible(false);
209     return realizer;
210   }
211 
212   /**
213    * Creates a configured edge realizer that represents a network connection.
214    */
215   public static EdgeRealizer createConnection() {
216     final GenericEdgeRealizer realizer = new GenericEdgeRealizer();
217     realizer.setConfiguration(CONFIGURATION_CONNECTION);
218     realizer.setUserData(new NetworkData(0));
219     final EdgeLabel label = realizer.getLabel();
220     label.setIcon(getWarningSign());
221     SmartEdgeLabelModel model = new SmartEdgeLabelModel();
222     label.setLabelModel(model, model.createDiscreteModelParameter(SmartEdgeLabelModel.POSITION_CENTER));
223     label.setVisible(false);
224     return realizer;
225   }
226 
227   /**
228    * Returns the {@link NetworkData} instance that belongs to the given edge realizer.
229    */
230   public static NetworkData getNetworkData(final EdgeRealizer context) {
231     if (context instanceof GenericEdgeRealizer) {
232       final GenericEdgeRealizer realizer = (GenericEdgeRealizer) context;
233       final Object userData = realizer.getUserData();
234       if (userData instanceof NetworkData) {
235         return (NetworkData) userData;
236       }
237     }
238     return null;
239   }
240 
241   /**
242    * Returns the {@link NetworkData} instance that belongs to the given node realizer.
243    */
244   public static NetworkData getNetworkData(final NodeRealizer context) {
245     if (context instanceof GenericNodeRealizer) {
246       final GenericNodeRealizer realizer = (GenericNodeRealizer) context;
247       final Object userData = realizer.getUserData();
248       if (userData instanceof NetworkData) {
249         return (NetworkData) userData;
250       }
251     }
252     return null;
253   }
254 
255   /**
256    * Returns a color that encodes the current status of the given network data.
257    */
258   static Color getStatusColor(NetworkData data) {
259     final Color displayColor;
260     if (data.isBroken()) {
261       return COLOR_BROKEN;
262     } else if (data.isDisabled()) {
263       return COLOR_DISABLED;
264     } else {
265       final double workload = data.getWorkload();
266       if (workload < 0.5) {
267         // the according color between green and yellow
268         final int red = (int) ((1 - 2 * workload) * COLOR_WORKLOAD_NONE.getRed() + 2 * workload * COLOR_WORKLOAD_HALF.getRed());
269         final int green = (int) ((1 - 2 * workload) * COLOR_WORKLOAD_NONE.getGreen() + 2 * workload * COLOR_WORKLOAD_HALF.getGreen());
270         final int blue = (int) ((1 - 2 * workload) * COLOR_WORKLOAD_NONE.getBlue() + 2 * workload * COLOR_WORKLOAD_HALF.getBlue());
271         displayColor = new Color(red, green, blue);
272       } else {
273         // the according color between yellow and red
274         final int red = (int) ((2 - 2 * workload) * COLOR_WORKLOAD_HALF.getRed() + (2 * workload - 1) * COLOR_WORKLOAD_FULL.getRed());
275         final int green = (int) ((2 - 2 * workload) * COLOR_WORKLOAD_HALF.getGreen() + (2 * workload - 1) * COLOR_WORKLOAD_FULL.getGreen());
276         final int blue = (int) ((2 - 2 * workload) * COLOR_WORKLOAD_HALF.getBlue() + (2 * workload - 1) * COLOR_WORKLOAD_FULL.getBlue());
277         displayColor = new Color(red, green, blue);
278       }
279       return displayColor;
280     }
281   }
282 
283   /**
284    * Paints a warning sign.
285    *
286    * @param x        the x-coordinate of the upper left corner of the signs bounding box in world-coordinates.
287    * @param y        the y-coordinate of the upper left corner of the signs bounding box in world-coordinates.
288    * @param width    the width of the signs bounding box.
289    * @param height   the height of the signs bounding box.
290    * @param graphics the current graphics context.
291    */
292   public static void paintWarningSign(double x, double y, double width, double height, Graphics2D graphics) {
293     final double a = height / (SQRT_2 + 1);
294     final double b = (height / (SQRT_2 + 1)) / SQRT_2;
295 
296     // paint octagon
297     final GeneralPath sign = new GeneralPath();
298     sign.moveTo((float) (x + width / 2 - a / 2), (float) y);
299     sign.lineTo((float) (x + width / 2 + a / 2), (float) y);
300     sign.lineTo((float) (x + width / 2 + a / 2 + b), (float) (y + b));
301     sign.lineTo((float) (x + width / 2 + a / 2 + b), (float) (y + b + a));
302     sign.lineTo((float) (x + width / 2 + a / 2), (float) (y + height));
303     sign.lineTo((float) (x + width / 2 - a / 2), (float) (y + height));
304     sign.lineTo((float) (x + width / 2 - a / 2 - b), (float) (y + b + a));
305     sign.lineTo((float) (x + width / 2 - a / 2 - b), (float) (y + b));
306     sign.closePath();
307 
308     graphics.setColor(Color.RED);
309     graphics.fill(sign);
310 
311     // paint upper part of exclamation point
312     sign.reset();
313     sign.moveTo((float) (x + width / 2 - a / 4), (float) (y + height * 0.1));
314     sign.lineTo((float) (x + width / 2 + a / 4), (float) (y + height * 0.1));
315     sign.lineTo((float) (x + width / 2 + b / 4), (float) (y + height * 0.7));
316     sign.lineTo((float) (x + width / 2 - b / 4), (float) (y + height * 0.7));
317     sign.closePath();
318 
319     graphics.setColor(Color.WHITE);
320     graphics.fill(sign);
321 
322     // paint lower part of exclamation point
323     sign.reset();
324     sign.moveTo((float) (x + width / 2 - b / 4), (float) (y + height * 0.85));
325     sign.quadTo((float) (x + width / 2 - b / 4), (float) (y + height * 0.85 - b / 4),
326         (float) (x + width / 2), (float) (y + height * 0.85 - b / 4));
327     sign.quadTo((float) (x + width / 2 + b / 4), (float) (y + height * 0.85 - b / 4),
328         (float) (x + width / 2 + b / 4), (float) (y + height * 0.85));
329     sign.quadTo((float) (x + width / 2 + b / 4), (float) (y + height * 0.85 + b / 4),
330         (float) (x + width / 2), (float) (y + height * 0.85 + b / 4));
331     sign.quadTo((float) (x + width / 2 - b / 4), (float) (y + height * 0.85 + b / 4),
332         (float) (x + width / 2 - b / 4), (float) (y + height * 0.85));
333     graphics.fill(sign);
334   }
335 
336   /**
337    * Returns an icon that shows a warning sign.
338    */
339   public static Icon getWarningSign() {
340     return WARNING_ICON;
341   }
342 
343   /**
344    * An {@link Icon} that shows a warning sign (exclamation point on an octagonal area).
345    */
346   private static class WarningIcon implements Icon {
347     private final int sideLength;
348 
349     /**
350      * Creates an instance of a warning sign.
351      *
352      * @param sideLength width or height of the quadratic base area.
353      */
354     public WarningIcon(int sideLength) {
355       this.sideLength = sideLength;
356     }
357 
358     /**
359      * Returns the height of the icon.
360      */
361     public int getIconHeight() {
362       return sideLength;
363     }
364 
365     /**
366      * Returns the width of the icon.
367      */
368     public int getIconWidth() {
369       return sideLength;
370     }
371 
372     public void paintIcon(Component c, Graphics g, int x, int y) {
373       final Graphics2D graphics = (Graphics2D) g.create();
374       paintWarningSign(x, y, getIconWidth(), getIconHeight(), graphics);
375       graphics.dispose();
376     }
377   }
378 }
379