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}