001/* 002 * Copyright 2006 - 2013 003 * Stefan Balev <stefan.balev@graphstream-project.org> 004 * Julien Baudry <julien.baudry@graphstream-project.org> 005 * Antoine Dutot <antoine.dutot@graphstream-project.org> 006 * Yoann Pigné <yoann.pigne@graphstream-project.org> 007 * Guilhelm Savin <guilhelm.savin@graphstream-project.org> 008 * 009 * This file is part of GraphStream <http://graphstream-project.org>. 010 * 011 * GraphStream is a library whose purpose is to handle static or dynamic 012 * graph, create them from scratch, file or any source and display them. 013 * 014 * This program is free software distributed under the terms of two licenses, the 015 * CeCILL-C license that fits European law, and the GNU Lesser General Public 016 * License. You can use, modify and/ or redistribute the software under the terms 017 * of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following 018 * URL <http://www.cecill.info> or under the terms of the GNU LGPL as published by 019 * the Free Software Foundation, either version 3 of the License, or (at your 020 * option) any later version. 021 * 022 * This program is distributed in the hope that it will be useful, but WITHOUT ANY 023 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 024 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 025 * 026 * You should have received a copy of the GNU Lesser General Public License 027 * along with this program. If not, see <http://www.gnu.org/licenses/>. 028 * 029 * The fact that you are presently reading this means that you have had 030 * knowledge of the CeCILL-C and LGPL licenses and that you accept their terms. 031 */ 032package org.graphstream.ui.swingViewer; 033 034import java.util.HashSet; 035 036import org.graphstream.stream.ProxyPipe; 037import org.graphstream.stream.SourceBase; 038 039/** 040 * Shell around a proxy pipe coming from the viewer allowing to put viewer 041 * listeners on a viewer that runs in a distinct thread. 042 * 043 * <p> 044 * This pipe is a probe that you can place in the event loop between the viewer 045 * and the graph. It will transmit all events coming from the viewer to the 046 * graph (or any sink you connect to it). But in addition it will monitor 047 * standard attribute changes to redistribute them to specify 048 * "viewer listeners". 049 * </p> 050 * 051 * <p> 052 * As any proxy pipe, a viewer pipe must be "pumped" to receive events coming 053 * from other threads. 054 * </p> 055 */ 056public class ViewerPipe extends SourceBase implements ProxyPipe { 057 // Attribute 058 059 private String id; 060 061 /** 062 * The incoming event stream. 063 */ 064 protected ProxyPipe pipeIn; 065 066 /** 067 * Listeners on the viewer specific events. 068 */ 069 protected HashSet<ViewerListener> viewerListeners = new HashSet<ViewerListener>(); 070 071 // Construction 072 073 /** 074 * A shell around a pipe coming from a viewer in another thread. 075 */ 076 protected ViewerPipe(String id, ProxyPipe pipeIn) { 077 this.id = id; 078 this.pipeIn = pipeIn; 079 pipeIn.addSink(this); 080 } 081 082 // Access 083 084 public String getId() { 085 return id; 086 } 087 088 // Commands 089 090 /* 091 * (non-Javadoc) 092 * 093 * @see org.graphstream.stream.ProxyPipe#pump() 094 */ 095 public void pump() { 096 pipeIn.pump(); 097 } 098 099 /* 100 * (non-Javadoc) 101 * 102 * @see org.graphstream.stream.ProxyPipe#blockingPump() 103 */ 104 public void blockingPump() throws InterruptedException { 105 pipeIn.blockingPump(); 106 } 107 108 /* 109 * (non-Javadoc) 110 * 111 * @see org.graphstream.stream.ProxyPipe#blockingPump(long) 112 */ 113 public void blockingPump(long timeout) throws InterruptedException { 114 pipeIn.blockingPump(timeout); 115 } 116 117 public void addViewerListener(ViewerListener listener) { 118 viewerListeners.add(listener); 119 } 120 121 public void removeViewerListener(ViewerListener listener) { 122 viewerListeners.remove(listener); 123 } 124 125 // Sink interface 126 127 /* 128 * (non-Javadoc) 129 * 130 * @see 131 * org.graphstream.stream.AttributeSink#edgeAttributeAdded(java.lang.String, 132 * long, java.lang.String, java.lang.String, java.lang.Object) 133 */ 134 public void edgeAttributeAdded(String sourceId, long timeId, String edgeId, 135 String attribute, Object value) { 136 sendEdgeAttributeAdded(sourceId, timeId, edgeId, attribute, value); 137 } 138 139 /* 140 * (non-Javadoc) 141 * 142 * @see 143 * org.graphstream.stream.AttributeSink#edgeAttributeChanged(java.lang.String 144 * , long, java.lang.String, java.lang.String, java.lang.Object, 145 * java.lang.Object) 146 */ 147 public void edgeAttributeChanged(String sourceId, long timeId, 148 String edgeId, String attribute, Object oldValue, Object newValue) { 149 sendEdgeAttributeChanged(sourceId, timeId, edgeId, attribute, oldValue, 150 newValue); 151 } 152 153 /* 154 * (non-Javadoc) 155 * 156 * @see 157 * org.graphstream.stream.AttributeSink#edgeAttributeRemoved(java.lang.String 158 * , long, java.lang.String, java.lang.String) 159 */ 160 public void edgeAttributeRemoved(String sourceId, long timeId, 161 String edgeId, String attribute) { 162 sendEdgeAttributeRemoved(sourceId, timeId, edgeId, attribute); 163 } 164 165 /* 166 * (non-Javadoc) 167 * 168 * @see 169 * org.graphstream.stream.AttributeSink#graphAttributeAdded(java.lang.String 170 * , long, java.lang.String, java.lang.Object) 171 */ 172 public void graphAttributeAdded(String sourceId, long timeId, 173 String attribute, Object value) { 174 sendGraphAttributeAdded(sourceId, timeId, attribute, value); 175 176 if (attribute.equals("ui.viewClosed") && value instanceof String) { 177 for (ViewerListener listener : viewerListeners) 178 listener.viewClosed((String) value); 179 180 sendGraphAttributeRemoved(id, attribute); 181 } else if (attribute.equals("ui.clicked") && value instanceof String) { 182 for (ViewerListener listener : viewerListeners) 183 listener.buttonPushed((String) value); 184 185 sendGraphAttributeRemoved(id, attribute); 186 } 187 } 188 189 /* 190 * (non-Javadoc) 191 * 192 * @see 193 * org.graphstream.stream.AttributeSink#graphAttributeChanged(java.lang. 194 * String, long, java.lang.String, java.lang.Object, java.lang.Object) 195 */ 196 public void graphAttributeChanged(String sourceId, long timeId, 197 String attribute, Object oldValue, Object newValue) { 198 sendGraphAttributeChanged(sourceId, timeId, attribute, oldValue, 199 newValue); 200 } 201 202 /* 203 * (non-Javadoc) 204 * 205 * @see 206 * org.graphstream.stream.AttributeSink#graphAttributeRemoved(java.lang. 207 * String, long, java.lang.String) 208 */ 209 public void graphAttributeRemoved(String sourceId, long timeId, 210 String attribute) { 211 sendGraphAttributeRemoved(sourceId, timeId, attribute); 212 } 213 214 /* 215 * (non-Javadoc) 216 * 217 * @see 218 * org.graphstream.stream.AttributeSink#nodeAttributeAdded(java.lang.String, 219 * long, java.lang.String, java.lang.String, java.lang.Object) 220 */ 221 public void nodeAttributeAdded(String sourceId, long timeId, String nodeId, 222 String attribute, Object value) { 223 sendNodeAttributeAdded(sourceId, timeId, nodeId, attribute, value); 224 225 if (attribute.equals("ui.clicked")) { 226 for (ViewerListener listener : viewerListeners) 227 listener.buttonPushed(nodeId); 228 } 229 } 230 231 /* 232 * (non-Javadoc) 233 * 234 * @see 235 * org.graphstream.stream.AttributeSink#nodeAttributeChanged(java.lang.String 236 * , long, java.lang.String, java.lang.String, java.lang.Object, 237 * java.lang.Object) 238 */ 239 public void nodeAttributeChanged(String sourceId, long timeId, 240 String nodeId, String attribute, Object oldValue, Object newValue) { 241 sendNodeAttributeChanged(sourceId, timeId, nodeId, attribute, oldValue, 242 newValue); 243 } 244 245 /* 246 * (non-Javadoc) 247 * 248 * @see 249 * org.graphstream.stream.AttributeSink#nodeAttributeRemoved(java.lang.String 250 * , long, java.lang.String, java.lang.String) 251 */ 252 public void nodeAttributeRemoved(String sourceId, long timeId, 253 String nodeId, String attribute) { 254 sendNodeAttributeRemoved(sourceId, timeId, nodeId, attribute); 255 256 if (attribute.equals("ui.clicked")) { 257 for (ViewerListener listener : viewerListeners) 258 listener.buttonReleased(nodeId); 259 } 260 } 261 262 /* 263 * (non-Javadoc) 264 * 265 * @see org.graphstream.stream.ElementSink#edgeAdded(java.lang.String, long, 266 * java.lang.String, java.lang.String, java.lang.String, boolean) 267 */ 268 public void edgeAdded(String sourceId, long timeId, String edgeId, 269 String fromNodeId, String toNodeId, boolean directed) { 270 sendEdgeAdded(sourceId, timeId, edgeId, fromNodeId, toNodeId, directed); 271 } 272 273 /* 274 * (non-Javadoc) 275 * 276 * @see org.graphstream.stream.ElementSink#edgeRemoved(java.lang.String, 277 * long, java.lang.String) 278 */ 279 public void edgeRemoved(String sourceId, long timeId, String edgeId) { 280 sendEdgeRemoved(sourceId, timeId, edgeId); 281 } 282 283 /* 284 * (non-Javadoc) 285 * 286 * @see org.graphstream.stream.ElementSink#graphCleared(java.lang.String, 287 * long) 288 */ 289 public void graphCleared(String sourceId, long timeId) { 290 sendGraphCleared(sourceId, timeId); 291 } 292 293 /* 294 * (non-Javadoc) 295 * 296 * @see org.graphstream.stream.ElementSink#nodeAdded(java.lang.String, long, 297 * java.lang.String) 298 */ 299 public void nodeAdded(String sourceId, long timeId, String nodeId) { 300 sendNodeAdded(sourceId, timeId, nodeId); 301 } 302 303 /* 304 * (non-Javadoc) 305 * 306 * @see org.graphstream.stream.ElementSink#nodeRemoved(java.lang.String, 307 * long, java.lang.String) 308 */ 309 public void nodeRemoved(String sourceId, long timeId, String nodeId) { 310 sendNodeRemoved(sourceId, timeId, nodeId); 311 } 312 313 /* 314 * (non-Javadoc) 315 * 316 * @see org.graphstream.stream.ElementSink#stepBegins(java.lang.String, 317 * long, double) 318 */ 319 public void stepBegins(String sourceId, long timeId, double step) { 320 sendStepBegins(sourceId, timeId, step); 321 } 322}