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.graphicGraph; 033 034import static org.graphstream.ui.graphicGraph.GraphPosLengthUtils.nodePosition; 035 036import java.util.ArrayList; 037import java.util.Collection; 038import java.util.Collections; 039import java.util.HashMap; 040import java.util.Iterator; 041 042import org.graphstream.graph.Edge; 043import org.graphstream.graph.Graph; 044import org.graphstream.graph.Node; 045import org.graphstream.stream.SourceBase.ElementType; 046import org.graphstream.ui.geom.Point3; 047import org.graphstream.ui.graphicGraph.stylesheet.Selector; 048 049/** 050 * Graphical node. 051 * 052 * <p> 053 * A graphic node defines a position (x,y,z), a string label, and a style from 054 * the style sheet. 055 * </p> 056 * 057 * @see GraphicGraph 058 */ 059public class GraphicNode extends GraphicElement implements Node { 060 /** 061 * The position of the node. In graph units. 062 */ 063 public double x, y, z; 064 065 public boolean positionned = false; 066 067 /** 068 * New graphic node. 069 * 070 * @param id 071 * The node identifier. 072 * @param attributes 073 * The node attribute set (can be null). 074 */ 075 public GraphicNode(GraphicGraph graph, String id, 076 HashMap<String, Object> attributes) { 077 super(id, graph); 078 079 if (attributes != null) 080 addAttributes(attributes); 081 } 082 083 @Override 084 public Selector.Type getSelectorType() { 085 return Selector.Type.NODE; 086 } 087 088 @Override 089 public double getX() { 090 return x; 091 } 092 093 @Override 094 public double getY() { 095 return y; 096 } 097 098 @Override 099 public double getZ() { 100 return z; 101 } 102 103 protected Point3 getPosition() { 104 return new Point3(x, y, z); 105 } 106 107 protected void moveFromEvent(double x, double y, double z) { 108 this.x = x; 109 this.y = y; 110 this.z = z; 111 112 if (!positionned) { 113 positionned = true; 114 } 115 116 mygraph.graphChanged = true; 117 mygraph.boundsChanged = true; 118 } 119 120 @Override 121 public void move(double x, double y, double z) { 122 moveFromEvent(x, y, z); 123 124 if (mygraph.feedbackXYZ) 125 setAttribute("xyz", x, y, z); 126 } 127 128 @Override 129 protected void attributeChanged(AttributeChangeEvent event, 130 String attribute, Object oldValue, Object newValue) { 131 super.attributeChanged(event, attribute, oldValue, newValue); 132 char c = attribute.charAt(0); 133 134 if (attribute.length() > 2 && c == 'u' && attribute.charAt(1) == 'i' 135 && attribute.startsWith("ui.sprite.")) { 136 mygraph.spriteAttribute(event, this, attribute, newValue); 137 } else if ((event == AttributeChangeEvent.ADD || event == AttributeChangeEvent.CHANGE)) { 138 if (attribute.length() == 1) { 139 switch (c) { 140 case 'x': 141 moveFromEvent(numberAttribute(newValue), y, z); 142 break; 143 case 'y': 144 moveFromEvent(x, numberAttribute(newValue), z); 145 break; 146 case 'z': 147 moveFromEvent(x, y, numberAttribute(newValue)); 148 break; 149 default: 150 break; 151 } 152 } else if (c == 'x' 153 && attribute.length() > 1 154 && attribute.charAt(1) == 'y' 155 && (attribute.length() == 2 || (attribute.length() == 3 && attribute 156 .charAt(2) == 'z'))) { 157 158 double pos[] = nodePosition(this); 159 moveFromEvent(pos[0], pos[1], pos[2]); 160 } 161 } 162 163 mygraph.listeners.sendAttributeChangedEvent(getId(), ElementType.NODE, 164 attribute, event, oldValue, newValue); 165 } 166 167 /** 168 * Try to convert the object to a double. 169 * 170 * @param value 171 * The object to convert. 172 * @return The value. 173 */ 174 protected double numberAttribute(Object value) { 175 if (value instanceof Number) { 176 return ((Number) value).doubleValue(); 177 } else if (value instanceof String) { 178 try { 179 return Double.parseDouble((String) value); 180 } catch (NumberFormatException e) { 181 } 182 } else if (value instanceof CharSequence) { 183 try { 184 return Double.parseDouble(((CharSequence) value).toString()); 185 } catch (NumberFormatException e) { 186 } 187 } 188 189 return 0; 190 } 191 192 @Override 193 protected void removed() { 194 // NOP 195 } 196 197 // Node interface. 198 199 /** 200 * Not implemented. 201 */ 202 public Iterator<Node> getBreadthFirstIterator() { 203 throw new RuntimeException("not implemented !"); 204 } 205 206 /** 207 * Not implemented. 208 */ 209 public Iterator<Node> getBreadthFirstIterator(boolean directed) { 210 throw new RuntimeException("not implemented !"); 211 } 212 213 /** 214 * Not implemented. 215 */ 216 public Iterator<Node> getDepthFirstIterator() { 217 throw new RuntimeException("not implemented !"); 218 } 219 220 /** 221 * Not implemented. 222 */ 223 public Iterator<Node> getDepthFirstIterator(boolean directed) { 224 throw new RuntimeException("not implemented !"); 225 } 226 227 public int getDegree() { 228 ArrayList<GraphicEdge> edges = mygraph.connectivity.get(this); 229 230 if (edges != null) 231 return edges.size(); 232 233 return 0; 234 } 235 236 @SuppressWarnings("unchecked") 237 public <T extends Edge> T getEdge(int i) { 238 ArrayList<GraphicEdge> edges = mygraph.connectivity.get(this); 239 240 if (edges != null && i >= 0 && i < edges.size()) 241 return (T) edges.get(i); 242 243 return null; 244 } 245 246 @SuppressWarnings("unchecked") 247 public <T extends Edge> T getEdgeBetween(String id) { 248 if (hasEdgeToward(id)) 249 return (T) getEdgeToward(id); 250 else 251 return (T) getEdgeFrom(id); 252 } 253 254 @SuppressWarnings("all") 255 public <T extends Edge> T getEdgeFrom(String id) { 256 return null; 257 } 258 259 @SuppressWarnings("unchecked") 260 public <T extends Edge> Iterator<T> getEdgeIterator() { 261 ArrayList<GraphicEdge> edges = mygraph.connectivity.get(this); 262 263 if (edges != null) 264 return (Iterator<T>) edges.iterator(); 265 266 return null; 267 } 268 269 @SuppressWarnings("all") 270 public Iterator<Edge> iterator() { 271 return (Iterator<Edge>) getEdgeIterator(); 272 } 273 274 @SuppressWarnings("all") 275 public <T extends Edge> Iterable<T> getEachEdge() { 276 return (Iterable<T>) mygraph.connectivity.get(this); 277 } 278 279 @SuppressWarnings("all") 280 public <T extends Edge> Collection<T> getEdgeSet() { 281 return (Collection<T>) Collections 282 .unmodifiableCollection(mygraph.connectivity.get(this)); 283 } 284 285 @SuppressWarnings("all") 286 public <T extends Edge> T getEdgeToward(String id) { 287 ArrayList<? extends Edge> edges = mygraph.connectivity.get(this); 288 289 for (Edge edge : edges) { 290 if (edge.getOpposite(this).getId().equals(id)) 291 return (T) edge; 292 } 293 294 return null; 295 } 296 297 @SuppressWarnings("all") 298 public <T extends Edge> Iterator<T> getEnteringEdgeIterator() { 299 return getEdgeIterator(); 300 } 301 302 @SuppressWarnings("all") 303 public <T extends Edge> Iterable<T> getEachEnteringEdge() { 304 return getEdgeSet(); 305 } 306 307 @SuppressWarnings("all") 308 public <T extends Edge> Collection<T> getEnteringEdgeSet() { 309 return (Collection<T>) Collections.unmodifiableCollection(getEdgeSet()); 310 } 311 312 public Graph getGraph() { 313 return mygraph; 314 } 315 316 public String getGraphName() { 317 throw new RuntimeException("impossible with GraphicGraph"); 318 } 319 320 public String getHost() { 321 throw new RuntimeException("impossible with GraphicGraph"); 322 } 323 324 public int getInDegree() { 325 return getDegree(); 326 } 327 328 @SuppressWarnings("all") 329 public <T extends Edge> Iterator<T> getLeavingEdgeIterator() { 330 return getEdgeIterator(); 331 } 332 333 @SuppressWarnings("all") 334 public <T extends Edge> Iterable<T> getEachLeavingEdge() { 335 return getEdgeSet(); 336 } 337 338 @SuppressWarnings("all") 339 public <T extends Edge> Collection<T> getLeavingEdgeSet() { 340 return (Collection<T>) Collections.unmodifiableCollection(getEdgeSet()); 341 } 342 343 public Iterator<Node> getNeighborNodeIterator() { 344 return null; 345 } 346 347 public int getOutDegree() { 348 return getDegree(); 349 } 350 351 public boolean hasEdgeBetween(String id) { 352 return (hasEdgeToward(id) || hasEdgeFrom(id)); 353 } 354 355 public boolean hasEdgeFrom(String id) { 356 return false; 357 } 358 359 public boolean hasEdgeToward(String id) { 360 return false; 361 } 362 363 public boolean isDistributed() { 364 return false; 365 } 366 367 public void setGraph(Graph graph) { 368 throw new RuntimeException("impossible with GraphicGraph"); 369 } 370 371 public void setGraphName(String newHost) { 372 throw new RuntimeException("impossible with GraphicGraph"); 373 } 374 375 public void setHost(String newHost) { 376 throw new RuntimeException("impossible with GraphicGraph"); 377 } 378 379 // XXX stubs for the new methods 380 381 public <T extends Edge> T getEdgeBetween(Node Node) { 382 // TODO Auto-generated method stub 383 return null; 384 } 385 386 public <T extends Edge> T getEdgeBetween(int index) { 387 // TODO Auto-generated method stub 388 return null; 389 } 390 391 public <T extends Edge> T getEdgeFrom(Node Node) { 392 // TODO Auto-generated method stub 393 return null; 394 } 395 396 public <T extends Edge> T getEdgeFrom(int index) { 397 // TODO Auto-generated method stub 398 return null; 399 } 400 401 public <T extends Edge> T getEdgeToward(Node Node) { 402 // TODO Auto-generated method stub 403 return null; 404 } 405 406 public <T extends Edge> T getEdgeToward(int index) { 407 // TODO Auto-generated method stub 408 return null; 409 } 410 411 public boolean hasEdgeBetween(Node node) { 412 // TODO Auto-generated method stub 413 return false; 414 } 415 416 public boolean hasEdgeBetween(int index) { 417 // TODO Auto-generated method stub 418 return false; 419 } 420 421 public boolean hasEdgeFrom(Node node) { 422 // TODO Auto-generated method stub 423 return false; 424 } 425 426 public boolean hasEdgeFrom(int index) { 427 // TODO Auto-generated method stub 428 return false; 429 } 430 431 public boolean hasEdgeToward(Node node) { 432 // TODO Auto-generated method stub 433 return false; 434 } 435 436 public boolean hasEdgeToward(int index) { 437 // TODO Auto-generated method stub 438 return false; 439 } 440 441 public <T extends Edge> T getEnteringEdge(int i) { 442 // TODO Auto-generated method stub 443 return null; 444 } 445 446 public <T extends Edge> T getLeavingEdge(int i) { 447 // TODO Auto-generated method stub 448 return null; 449 } 450}