1
28 package demo.view.networkmonitoring;
29
30 import y.anim.AnimationFactory;
31 import y.anim.AnimationObject;
32 import y.anim.AnimationPlayer;
33 import y.anim.CompositeAnimationObject;
34 import y.base.DataMap;
35 import y.base.DataProvider;
36 import y.base.Edge;
37 import y.base.EdgeCursor;
38 import y.base.Node;
39 import y.base.NodeCursor;
40 import y.layout.labeling.SALabeling;
41 import y.util.Maps;
42 import y.view.Drawable;
43 import y.view.EdgeLabel;
44 import y.view.EdgeRealizer;
45 import y.view.GenericEdgeRealizer;
46 import y.view.GenericNodeRealizer;
47 import y.view.Graph2D;
48 import y.view.Graph2DLayoutExecutor;
49 import y.view.Graph2DView;
50 import y.view.LineType;
51 import y.view.NodeLabel;
52 import y.view.NodeRealizer;
53 import y.view.ViewAnimationFactory;
54
55 import java.awt.Graphics2D;
56 import java.awt.Rectangle;
57 import java.awt.geom.GeneralPath;
58 import java.awt.geom.Point2D;
59 import java.awt.geom.Rectangle2D;
60 import java.beans.PropertyChangeEvent;
61 import java.beans.PropertyChangeListener;
62 import java.util.HashSet;
63
64
67 class NetworkView implements NetworkModelObserver {
68 private static final TrafficMarker TRAFFIC_MARKER = new TrafficMarker();
69
70 private final NetworkModel model;
71 private final Graph2DView view;
72 private final DataMap view2model;
73 private final HashSet brokenElements;
74 private final AnimationPlayer zoomDependentPlayer;
75
76 public NetworkView(NetworkModel model, Graph2DView view, DataMap view2model) {
77 this.model = model;
78 this.view = view;
79 this.view2model = view2model;
80
81 final Graph2D modelGraph = model.getNetworkModel();
82 final Graph2D viewGraph = view.getGraph2D();
83 final DataProvider nodeTypes = modelGraph.getDataProvider(NetworkModel.NODE_TYPE_DPKEY);
84 final DataProvider elementIds = modelGraph.getDataProvider(NetworkModel.ELEMENT_ID_DPKEY);
85 final DataProvider edgeCapacities = modelGraph.getDataProvider(NetworkModel.ELEMENT_CAPACITY_DPKEY);
86 final DataProvider nodeInfos = modelGraph.getDataProvider(NetworkModel.NODE_INFO_DPKEY);
87
88 brokenElements = new HashSet(modelGraph.nodeCount() + modelGraph.edgeCount());
89
90 zoomDependentPlayer = createZoomDependentPlayer(view);
91
92 final DataMap model2view = Maps.createHashedDataMap();
94 for (NodeCursor nc = modelGraph.nodes(); nc.ok(); nc.next()) {
95 final Node modelNode = nc.node();
96 final Node viewNode = viewGraph.createNode();
97 if (nodeTypes != null && nodeTypes.get(modelNode) != null) {
98 NodeRealizer realizer;
99 switch (nodeTypes.getInt(modelNode)) {
100 case NetworkModel.PC:
101 realizer = NetworkMonitoringFactory.createWorkstation();
102 break;
103 case NetworkModel.LAPTOP:
104 realizer = NetworkMonitoringFactory.createLaptop();
105 break;
106 case NetworkModel.SMARTPHONE:
107 realizer = NetworkMonitoringFactory.createSmartphone();
108 break;
109 case NetworkModel.SWITCH:
110 realizer = NetworkMonitoringFactory.createSwitch();
111 break;
112 case NetworkModel.WLAN:
113 realizer = NetworkMonitoringFactory.createWLan();
114 break;
115 case NetworkModel.DATABASE:
116 realizer = NetworkMonitoringFactory.createDatabase();
117 break;
118 case NetworkModel.SERVER:
119 realizer = NetworkMonitoringFactory.createServer();
120 break;
121 default:
122 realizer = new GenericNodeRealizer();
123 }
124 final NodeLabel infoLabel = realizer.getLabel();
125 if (infoLabel != null) {
126 final NetworkNodeInfo nodeInfo = (NetworkNodeInfo) nodeInfos.get(modelNode);
127 infoLabel.setText(nodeInfo.getName() + "\n" + nodeInfo.getIpAddress());
128
129 if (viewNode.index() % 9 == 0) {
131 infoLabel.setVisible(true);
132 }
133 }
134 realizer.setCenter(modelGraph.getCenterX(modelNode), modelGraph.getCenterY(modelNode));
135 viewGraph.setRealizer(viewNode, realizer);
136 }
137 if (elementIds != null && elementIds.get(modelNode) != null) {
138 final Object id = elementIds.get(modelNode);
139 view2model.set(viewNode, id);
140 model2view.set(id, viewNode);
141 }
142 }
143
144 int maxCapacity = 0;
146 if (edgeCapacities != null) {
147 for (EdgeCursor ec = modelGraph.edges(); ec.ok(); ec.next()) {
148 final Edge edge = ec.edge();
149 final int capacity = edgeCapacities.getInt(edge);
150 if (capacity > maxCapacity) {
151 maxCapacity = capacity;
152 }
153 }
154 }
155 for (EdgeCursor ec = modelGraph.edges(); ec.ok(); ec.next()) {
157 final Edge modelEdge = ec.edge();
158 if (elementIds != null) {
159 final Edge viewEdge = viewGraph.createEdge((Node) model2view.get(elementIds.get(modelEdge.source())),
160 (Node) model2view.get(elementIds.get(modelEdge.target())));
161 final EdgeRealizer realizer = NetworkMonitoringFactory.createConnection();
162 viewGraph.setRealizer(viewEdge, realizer);
163 if (edgeCapacities != null) {
164 final int capacity = edgeCapacities.getInt(modelEdge);
165 if (capacity < maxCapacity * 0.33) {
166 realizer.setLineType(LineType.LINE_3);
167 } else if (capacity < maxCapacity * 0.66) {
168 realizer.setLineType(LineType.LINE_5);
169 } else {
170 realizer.setLineType(LineType.LINE_7);
171 }
172 }
173 final Object id = elementIds.get(modelEdge);
174 view2model.set(viewEdge, id);
175 model2view.set(id, viewEdge);
176 }
177 }
178
179 final SALabeling labeling = new SALabeling();
181 labeling.setPlaceNodeLabels(true);
182 labeling.setPlaceEdgeLabels(false);
183 labeling.setRemoveNodeOverlaps(true);
184 labeling.setDeterministicModeEnabled(true);
185 new Graph2DLayoutExecutor().doLayout(viewGraph, labeling);
186 }
187
188
191 private AnimationPlayer createZoomDependentPlayer(Graph2DView view) {
192 final ViewAnimationFactory factory = new ViewAnimationFactory(view);
193 final AnimationPlayer player = factory.createConfiguredPlayer();
194
195 view.getCanvasComponent().addPropertyChangeListener(new PropertyChangeListener() {
196 public void propertyChange(PropertyChangeEvent evt) {
197 if ("Zoom".equals(evt.getPropertyName())) {
198 final double zoom = ((Double) evt.getNewValue()).doubleValue();
199 if (zoom <= NetworkMonitoringDemo.PAINT_DETAIL_THRESHOLD
200 && player.isPlaying()) {
201 player.stop();
202 }
203 }
204 }
205 });
206
207 return player;
208 }
209
210
213 public void update(DataMap dataMap) {
214 final Graph2D viewGraph = view.getGraph2D();
215 Rectangle2D focusRect = null;
216 for (NodeCursor nodeCursor = viewGraph.nodes(); nodeCursor.ok(); nodeCursor.next()) {
217 final Node viewNode = nodeCursor.node();
218 if (dataMap.get(view2model.get(viewNode)) != null) {
219 final double workload = ((Double) dataMap.get(view2model.get(viewNode))).doubleValue();
220 final NodeRealizer realizer = viewGraph.getRealizer(viewNode);
221 if (realizer instanceof GenericNodeRealizer) {
222 final GenericNodeRealizer gnr = (GenericNodeRealizer) realizer;
223 final NetworkData networkData = (NetworkData) gnr.getUserData();
224 networkData.setWorkload(workload);
225 if (networkData.isBroken() && !brokenElements.contains(viewNode)) {
226 brokenElements.add(viewNode);
227 if (focusRect == null) {
230 focusRect = new Rectangle2D.Double(0, 0, -1, -1);
231 }
232 focusRect.setFrame(realizer.getX(), realizer.getY(), realizer.getWidth(), realizer.getHeight());
233 } else if (!networkData.isBroken() && brokenElements.contains(viewNode)) {
234 brokenElements.remove(viewNode);
235 }
236 }
237 }
238 }
239 for (EdgeCursor ec = viewGraph.edges(); ec.ok(); ec.next()) {
240 final Edge viewEdge = ec.edge();
241 final EdgeRealizer realizer = viewGraph.getRealizer(viewEdge);
242 if (realizer instanceof GenericEdgeRealizer) {
243 final GenericEdgeRealizer ger = (GenericEdgeRealizer) realizer;
244 final NetworkData networkData = (NetworkData) ger.getUserData();
245 if (dataMap.get(view2model.get(viewEdge)) != null) {
246 final double workload = ((Double) dataMap.get(view2model.get(viewEdge))).doubleValue();
247 networkData.setWorkload(workload);
248 final EdgeLabel errorLabel = realizer.getLabel();
249 if (networkData.isBroken() && !brokenElements.contains(viewEdge)) {
250 brokenElements.add(viewEdge);
251 if (focusRect == null) {
254 focusRect = new Rectangle2D.Double(0, 0, -1, -1);
255 }
256 final Node source = viewEdge.source();
257 final Node target = viewEdge.target();
258 final double sourceX = viewGraph.getX(source);
259 final double targetX = viewGraph.getX(target);
260 final double sourceY = viewGraph.getY(source);
261 final double targetY = viewGraph.getY(target);
262 final double minX = Math.min(sourceX, targetX);
263 final double minY = Math.min(sourceY, targetY);
264 final double maxX = Math.max(sourceX + viewGraph.getWidth(source), targetX + viewGraph.getWidth(target));
265 final double maxY = Math.max(sourceY + viewGraph.getHeight(source), targetY + viewGraph.getHeight(target));
266 focusRect.setFrameFromDiagonal(minX, minY, maxX, maxY);
267 errorLabel.setVisible(true);
268 } else if (!networkData.isBroken() && brokenElements.contains(viewEdge)) {
269 brokenElements.remove(viewEdge);
270 errorLabel.setVisible(false);
271 }
272 }
273 }
274 }
275
276 final int stepDuration = model.getUpdateCycle();
278
279 if (focusRect != null && !view.getVisibleRect().contains(focusRect)
281 && (focusRect.getCenterX() != view.getCenter().getX() || focusRect.getCenterY() != view.getCenter().getY())) {
282 final AnimationPlayer player = new ViewAnimationFactory(view).createConfiguredPlayer();
283 player.animate(createFocusViewAnimation(focusRect, stepDuration));
284 }
285 if (view.getZoom() > NetworkMonitoringDemo.PAINT_DETAIL_THRESHOLD) {
286 zoomDependentPlayer.animate(createConnectionAnimation(stepDuration, dataMap));
287 } else {
288 view.updateView();
289 }
290 }
291
292
295 private AnimationObject createFocusViewAnimation(Rectangle2D focusRect, int duration) {
296 final Point2D newCenter = new Point2D.Double(focusRect.getCenterX(), focusRect.getCenterY());
298
299 final int newZoom = 1;
300 final double intermediateZoom = Math.max(NetworkMonitoringDemo.MIN_ZOOM, Math.min(view.getZoom(), newZoom) - 0.4);
301 return AnimationFactory.createEasedAnimation(
302 new FocusViewAnimation(newCenter, newZoom, intermediateZoom, duration));
303 }
304
305
308 private AnimationObject createConnectionAnimation(int duration, DataMap dataMap) {
309 final Graph2D graph = view.getGraph2D();
310 final ViewAnimationFactory factory = new ViewAnimationFactory(view);
311 final CompositeAnimationObject concurrency = AnimationFactory.createConcurrency();
312
313 for (EdgeCursor ec = graph.edges(); ec.ok(); ec.next()) {
314 final Edge edge = ec.edge();
315 final EdgeRealizer realizer = graph.getRealizer(edge);
316 final NetworkData networkData = NetworkMonitoringFactory.getNetworkData(realizer);
317 if (dataMap.get(view2model.get(edge)) != null && networkData != null && networkData.getWorkload() > 0) {
318 final GeneralPath path = realizer.getPath();
319 concurrency.addAnimation(factory.traversePath(path, false, TRAFFIC_MARKER, duration));
320 concurrency.addAnimation(factory.traversePath(path, true, TRAFFIC_MARKER, duration));
321 }
322 }
323
324 return concurrency;
325 }
326
327
330 private static class TrafficMarker implements Drawable {
331 private static final int WIDTH = 6;
332 private static final int HEIGHT = 6;
333
334 public void paint(final Graphics2D g) {
335 final Rectangle bounds = getBounds();
336 g.drawOval(0, 0, bounds.width, bounds.height);
337 }
338
339 public Rectangle getBounds() {
340 return new Rectangle(0, 0, WIDTH, HEIGHT);
341 }
342 }
343
344
348 private class FocusViewAnimation implements AnimationObject {
349 private final Point2D newCenter;
350 private final double intermediateZoom;
351 private final double newZoom;
352 private final long preferredDuration;
353 private Point2D oldCenter;
354 private double oldZoom;
355
356 public FocusViewAnimation(Point2D newCenter, double newZoom, double intermediateZoom, long preferredDuration) {
357 this.newCenter = newCenter;
358 this.newZoom = newZoom;
359 this.intermediateZoom = intermediateZoom;
360 this.preferredDuration = preferredDuration;
361 }
362
363 public void initAnimation() {
364 oldCenter = view.getCenter();
365 oldZoom = view.getZoom();
366 }
367
368 public void calcFrame(double time) {
369 view.setCenter(
371 (newCenter.getX() - oldCenter.getX()) * time + oldCenter.getX(),
372 (newCenter.getY() - oldCenter.getY()) * time + oldCenter.getY());
373
374 view.setZoom((1 - time) * (1 - time) * oldZoom + 2 * time * (1 - time) * intermediateZoom + time * time * newZoom);
376 }
377
378 public void disposeAnimation() {
379 }
380
381 public long preferredDuration() {
382 return preferredDuration;
383 }
384 }
385 }
386