Package org.graphstream.ui.spriteManager

Source Code of org.graphstream.ui.spriteManager.Sprite

/*
* Copyright 2006 - 2013
*     Stefan Balev     <stefan.balev@graphstream-project.org>
*     Julien Baudry    <julien.baudry@graphstream-project.org>
*     Antoine Dutot    <antoine.dutot@graphstream-project.org>
*     Yoann Pigné      <yoann.pigne@graphstream-project.org>
*     Guilhelm Savin   <guilhelm.savin@graphstream-project.org>
*
* This file is part of GraphStream <http://graphstream-project.org>.
*
* GraphStream is a library whose purpose is to handle static or dynamic
* graph, create them from scratch, file or any source and display them.
*
* This program is free software distributed under the terms of two licenses, the
* CeCILL-C license that fits European law, and the GNU Lesser General Public
* License. You can  use, modify and/ or redistribute the software under the terms
* of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
* URL <http://www.cecill.info> or under the terms of the GNU LGPL as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
*/
package org.graphstream.ui.spriteManager;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.graphstream.graph.Element;
import org.graphstream.ui.graphicGraph.stylesheet.Style;
import org.graphstream.ui.graphicGraph.stylesheet.Values;

/**
* A gentle little sprite.
*
* <p>
* Sprite objects allow to add data representations in a graphic display of a
* graph. A sprite is a graphical representation that can double anywhere in the
* graph drawing surface, or be "attached" to nodes or edges. When attached to
* an edge, a sprite can be positioned easily at any point along the edge, or
* perpendicular to it with one or two coordinates. When attached to a node, a
* sprite "orbits" around the node at any given radius and angle around it.
* </p>
*
* <p>
* Sprites can have many shapes. Most of the CSS nodes shapes are available for
* sprites, but more are possible. Some shapes follow the form of the element
* (node or edge) they are attached to.
* </p>
*
* <p>
* Sprites can be moved and animated easily along edges, around nodes, or
* anywhere on the graph surface. Their shape can change. Some sprites allows to
* draw pie charts or statistics, or images.
* </p>
*
* <p>
* Sprites are not part of a graph so to speak. Furthermore they make sense only
* when a graph is displayed with a viewer that supports sprites. Therefore they
* are handled by a {@link SpriteManager} which is always associated to a graph
* and is in charge of handling the whole set of sprites, creating them,
* enumerating them, and destroying them.
* </p>
*
* <p>
* Implementation note: sprites do not exist ! In fact the sprite class only
* handles a set of attributes that are stored in the graph (the one associated
* with the sprite manager that created the sprite). These special attributes
* are handled for you by the sprite class. This technique allows to pass
* sprites informations through the I/O system of GraphStream. Indeed sprites
* appearing in a graph can therefore be stored in files and retrieved if the
* graph file format supports attributes. If this is a dynamic graph format,
* like DGS, the whole sprite history is remembered: when it moved, when it
* changed, etc.
* </p>
*
* <p>
* Second implementation node : often you will need to extend the sprite class.
* This is easily possible, but you must remember that you cannot create sprites
* yourself, you must use the {@link SpriteManager}. In order to create a sprite
* of a special kind, you can either use a {@link SpriteFactory} with the
* SpriteManager or the special {@link SpriteManager#addSprite(String, Class)}
* method of the SpriteManager. In both cases, the
* {@link #init(String, SpriteManager, Values)} method of the sprite will be
* called. Override this method to initialise your sprite.
* </p>
*
* @see SpriteManager
* @see SpriteFactory
*/
public class Sprite implements Element {
  // Attribute

  /**
   * The sprite unique identifier.
   */
  protected String id;

  /**
   * The identifier prefixed by "ui.sprite.".
   */
  protected String completeId;

  /**
   * The boss.
   */
  protected SpriteManager manager;

  /**
   * Current sprite position.
   */
  protected Values position;

  /**
   * The element this sprite is attached to (or null).
   */
  protected Element attachment;

  // Construction

  /** For the use with {@link #init(String, SpriteManager, Values)}. */
  protected Sprite() {
  }

  /**
   * New sprite with a given identifier.
   *
   * You cannot build sprites yourself, they are created by the sprite
   * manager.
   */
  protected Sprite(String id, SpriteManager manager) {
    this(id, manager, null);
  }

  /**
   * New sprite with a given identifier.
   *
   * You cannot build sprites yourself, they are created by the sprite
   * manager.
   */
  protected Sprite(String id, SpriteManager manager, Values position) {
    init(id, manager, position);
  }

  /**
   * New sprite with a given identifier.
   *
   * You cannot build sprites yourself, they are created by the sprite
   * managern. This method is used by the manager when creating instances of
   * sprites that inherit this class. If you derive the sprite class you can
   * override this method to initialise your sprite. It is always called when
   * creating the sprite.
   */
  protected void init(String id, SpriteManager manager, Values position) {
    this.id = id;
    this.completeId = String.format("ui.sprite.%s", id);
    this.manager = manager;

    if (!manager.graph.hasAttribute(completeId)) {
      if (position != null) {
        manager.graph.addAttribute(completeId, position);
        this.position = position;
      } else {
        this.position = new Values(Style.Units.GU, 0f, 0f, 0f);
        manager.graph.addAttribute(completeId, this.position);
      }
    } else {
      if (position != null) {
        manager.graph.setAttribute(completeId, position);
        this.position = position;
      } else {
        this.position = SpriteManager.getPositionValue(manager.graph
            .getAttribute(completeId));
      }
    }
  }

  /**
   * Called by the manager when the sprite is removed.
   */
  protected void removed() {
    manager.graph.removeAttribute(completeId);

    String start = String.format("%s.", completeId);

    if (attached())
      detach();

    ArrayList<String> keys = new ArrayList<String>();

    for (String key : manager.graph.getAttributeKeySet()) {
      if (key.startsWith(start))
        keys.add(key);
    }

    for (String key : keys)
      manager.graph.removeAttribute(key);
  }

  // Access

  /**
   * The element the sprite is attached to or null if the sprite is not
   * attached.
   *
   * @return An element the sprite is attached to or null.
   */
  public Element getAttachment() {
    return attachment;
  }

  /**
   * True if attached to an edge or node.
   *
   * @return False if not attached.
   */
  public boolean attached() {
    return (attachment != null);
  }

  /**
   * X position.
   *
   * @return The position in abscissa.
   */
  public double getX() {
    if (position.values.size() > 0)
      return position.values.get(0);

    return 0;
  }

  /**
   * Y position.
   *
   * @return The position in ordinate.
   */
  public double getY() {
    if (position.values.size() > 1)
      return position.values.get(1);

    return 0;
  }

  /**
   * Z position.
   *
   * @return The position in depth.
   */
  public double getZ() {
    if (position.values.size() > 2)
      return position.values.get(2);

    return 0;
  }

  public Style.Units getUnits() {
    return position.units;
  }

  // Command

  /**
   * Attach the sprite to a node with the given identifier. If needed the
   * sprite is first detached. If the given node identifier does not exist,
   * the sprite stays in detached state.
   *
   * @param id
   *            Identifier of the node to attach to.
   */
  public void attachToNode(String id) {
    if (attachment != null)
      detach();

    attachment = manager.graph.getNode(id);

    if (attachment != null)
      attachment.addAttribute(completeId);
  }

  /**
   * Attach the sprite to an edge with the given identifier. If needed the
   * sprite is first detached. If the given edge identifier does not exist,
   * the sprite stays in detached state.
   *
   * @param id
   *            Identifier of the edge to attach to.
   */
  public void attachToEdge(String id) {
    if (attachment != null)
      detach();

    attachment = manager.graph.getEdge(id);

    if (attachment != null)
      attachment.addAttribute(completeId);
  }

  /**
   * Detach the sprite from the element it is attached to (if any).
   */
  public void detach() {
    if (attachment != null) {
      attachment.removeAttribute(completeId);
      attachment = null;
    }
  }

  public void setPosition(double percent) {
    setPosition(position.units, percent, 0, 0);
  }

  public void setPosition(double x, double y, double z) {
    setPosition(position.units, x, y, z);
  }

  public void setPosition(Style.Units units, double x, double y, double z) {
    boolean changed = false;

    if (position.get(0) != x) {
      changed = true;
      position.setValue(0, x);
    }
    if (position.get(1) != y) {
      changed = true;
      position.setValue(1, y);
    }
    if (position.get(2) != z) {
      changed = true;
      position.setValue(2, z);
    }
    if (position.units != units) {
      changed = true;
      position.setUnits(units);
    }

    if (changed)
      manager.graph.setAttribute(completeId, new Values(position));
  }

  protected void setPosition(Values values) {
    if (values != null) {
      int n = values.values.size();

      if (n > 2) {
        setPosition(values.units, values.get(0), values.get(1),
            values.get(2));
      } else if (n > 0) {
        setPosition(values.get(0));
      }
    }
  }

  // Access (Element)

  public String getId() {
    return id;
  }

  public CharSequence getLabel(String key) {
    return manager.graph.getLabel(String.format("%s.%s", completeId, key));
  }

  public <T> T getAttribute(String key) {
    return manager.graph.getAttribute(String.format("%s.%s", completeId,
        key));
  }

  public <T> T getAttribute(String key, Class<T> clazz) {
    return manager.graph.getAttribute(
        String.format("%s.%s", completeId, key), clazz);
  }

  /**
   * Quite expensive operation !.
   */
  public int getAttributeCount() {
    String start = String.format("%s.", completeId);
    int count = 0;

    for (String key : manager.graph.getAttributeKeySet()) {
      if (key.startsWith(start))
        count++;
    }

    return count;
  }

  public Iterator<String> getAttributeKeyIterator() {
    throw new RuntimeException("not implemented");
  }
 
  public Iterable<String> getEachAttributeKey() {
    return getAttributeKeySet();
  }

  public Collection<String> getAttributeKeySet() {
    throw new RuntimeException("not implemented");
  }

  public Map<String, Object> getAttributeMap() {
    throw new RuntimeException("not implemented");
  }

  public <T> T getFirstAttributeOf(String... keys) {
    String completeKeys[] = new String[keys.length];
    int i = 0;

    for (String key : keys) {
      completeKeys[i] = String.format("%s.%s", completeId, key);
      i++;
    }

    return manager.graph.getFirstAttributeOf(completeKeys);
  }

  public <T> T getFirstAttributeOf(Class<T> clazz, String... keys) {
    String completeKeys[] = new String[keys.length];
    int i = 0;

    for (String key : keys) {
      completeKeys[i] = String.format("%s.%s", completeId, key);
      i++;
    }

    return manager.graph.getFirstAttributeOf(clazz, completeKeys);
  }

  public Object[] getArray(String key) {
    return manager.graph.getArray(String.format("%s.%s", completeId, key));
  }

  public HashMap<?, ?> getHash(String key) {
    return manager.graph.getHash(String.format("%s.%s", completeId, key));
  }

  public double getNumber(String key) {
    return manager.graph.getNumber(String.format("%s.%s", completeId, key));
  }

  public ArrayList<? extends Number> getVector(String key) {
    return manager.graph.getVector(String.format("%s.%s", completeId, key));
  }

  public boolean hasAttribute(String key) {
    return manager.graph.hasAttribute(String.format("%s.%s", completeId,
        key));
  }

  public boolean hasArray(String key) {
    return manager.graph.hasArray(String.format("%s.%s", completeId, key));
  }

  public boolean hasAttribute(String key, Class<?> clazz) {
    return manager.graph.hasAttribute(
        String.format("%s.%s", completeId, key), clazz);
  }

  public boolean hasHash(String key) {
    return manager.graph.hasHash(String.format("%s.%s", completeId, key));
  }

  public boolean hasLabel(String key) {
    return manager.graph.hasLabel(String.format("%s.%s", completeId, key));
  }

  public boolean hasNumber(String key) {
    return manager.graph.hasNumber(String.format("%s.%s", completeId, key));
  }

  public boolean hasVector(String key) {
    return manager.graph.hasVector(String.format("%s.%s", completeId, key));
  }

  // Commands (Element)

  public void addAttribute(String attribute, Object... values) {
    manager.graph.addAttribute(
        String.format("%s.%s", completeId, attribute), values);
  }

  public void addAttributes(Map<String, Object> attributes) {
    for (String key : attributes.keySet())
      manager.graph.addAttribute(String.format("%s.%s", completeId, key),
          attributes.get(key));
  }

  public void setAttribute(String attribute, Object... values) {
    manager.graph.setAttribute(
        String.format("%s.%s", completeId, attribute), values);
  }

  public void changeAttribute(String attribute, Object... values) {
    manager.graph.changeAttribute(
        String.format("%s.%s", completeId, attribute), values);
  }

  public void clearAttributes() {
    String start = String.format("%s.", completeId);
    ArrayList<String> keys = new ArrayList<String>();

    for (String key : manager.graph.getAttributeKeySet()) {
      if (key.startsWith(start))
        keys.add(key);
    }

    for (String key : keys)
      manager.graph.removeAttribute(key);
  }

  public void removeAttribute(String attribute) {
    manager.graph.removeAttribute(String.format("%s.%s", completeId,
        attribute));
  }
 
  // XXX -> UGLY FIX
  // Sprites do not have unique index but is this useful?
  public int getIndex() {
    return 0;
  }
}
TOP

Related Classes of org.graphstream.ui.spriteManager.Sprite

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.