public ObservableCachingLayout(Layout<V, E> delegate) {
   super(delegate);
   this.locationMap =
       LazyMap.<V, Point2D>decorate(
           new HashMap<V, Point2D>(),
           new ChainedTransformer<V, Point2D>(
               new Transformer[] {delegate, CloneTransformer.<Point2D>getInstance()}));
 }
public abstract class ClusteringGraphApplet extends JApplet
    implements ClusterUIConstants, ParameterConstants {
  private static final long serialVersionUID = 7065366231144981930L;

  /** The view of which this applet is a part. */
  protected ClusteringView view = null;

  protected static final String FILTER_COMMAND = "filter";

  protected static NodeNameComparator nodeNameComparator = new NodeNameComparator();

  protected static final UtilLogger logger = new UtilLogger("ClusteringGraphApplet");

  protected Paint CONNECTED_EDGE_COLOR = Color.BLACK;
  protected Paint DELETED_EDGE_COLOR = Color.GRAY;
  protected Paint PICKED_COLOR = Color.CYAN;
  protected Paint UNPICKED_COLOR = Color.BLACK;

  /** The clusterer that works on the graph. */
  protected ClustererIfc<CallGraphNode> clusterer = null;

  /** The graph to display. */
  protected JavaCallGraph graph = null;

  protected ApplicationParameters parameters = null;

  protected VisualizationViewer<CallGraphNode, CallGraphLink> visualizer;

  protected JPanel sliderPanel = null;

  protected JSlider iterationSlider = null;

  protected Object[] membersToIgnore = null;

  protected String sliderLabelBase = "Iteration: ";

  /** A text area in another component to which this writes. */
  // TODO avoid aliasing problems
  protected JTextArea clustersTextArea = null;

  @SuppressWarnings({"unchecked", "rawtypes"})
  protected Map<CallGraphNode, Paint> vertexPaints =
      LazyMap.<CallGraphNode, Paint>decorate(
          new HashMap<CallGraphNode, Paint>(), new ConstantTransformer(Color.white));

  @SuppressWarnings({"unchecked", "rawtypes"})
  protected Map<CallGraphLink, Paint> edgePaints =
      LazyMap.<CallGraphLink, Paint>decorate(
          new HashMap<CallGraphLink, Paint>(), new ConstantTransformer(Color.blue));

  public ClusteringGraphApplet() throws HeadlessException {
    super();
    parameters = ApplicationParameters.getSingleton();
    int iColor = parameters.getIntParameter(CONNECTED_EDGE_COLOR_KEY, BLACK_RGB);
    CONNECTED_EDGE_COLOR = new Color(iColor);
    iColor = parameters.getIntParameter(DELETED_EDGE_COLOR_KEY, GREY_RGB);
    DELETED_EDGE_COLOR = new Color(iColor);
    iColor = parameters.getIntParameter(PICKED_COLOR_KEY, CYAN_RGB);
    PICKED_COLOR = new Color(iColor);
    iColor = parameters.getIntParameter(UNPICKED_COLOR_KEY, BLACK_RGB);
    UNPICKED_COLOR = new Color(iColor);
  }

  public void start() {}

  /** @param clustersTextArea the clustersTextArea to set */
  public void setClustersTextArea(JTextArea clustersTextArea) {
    this.clustersTextArea = clustersTextArea;
  }

  protected void setRenderContextTransformers() {
    RenderContext<CallGraphNode, CallGraphLink> renderContext = visualizer.getRenderContext();
    setRenderContextVertexTransformers(renderContext);
    setRenderContextEdgeTransformers(renderContext);
  }

  protected void setRenderContextEdgeTransformers(
      RenderContext<CallGraphNode, CallGraphLink> renderContext) {
    setEdgeLabeler(renderContext);
    renderContext.setEdgeDrawPaintTransformer(
        MapTransformer.<CallGraphLink, Paint>getInstance(edgePaints));
    renderContext.setEdgeStrokeTransformer(
        new Transformer<CallGraphLink, Stroke>() {
          protected final Stroke THIN = new BasicStroke(1);
          protected final Stroke THICK = new BasicStroke(2);

          public Stroke transform(CallGraphLink e) {
            Paint c = edgePaints.get(e);
            if (c == Color.LIGHT_GRAY) return THIN;
            else return THICK;
          }
        });
  }

  protected void setRenderContextVertexTransformers(
      RenderContext<CallGraphNode, CallGraphLink> renderContext) {
    setVertexLabeler(renderContext);
    renderContext.setVertexFillPaintTransformer(new NodeTypeColorer());
    //	    		MapTransformer.<CallGraphNode, Paint> getInstance(vertexPaints));
    setVertexDrawPaintTransformer(renderContext);
    setVertexShapeTransformer(renderContext);
  }

  protected void setVertexDrawPaintTransformer(
      RenderContext<CallGraphNode, CallGraphLink> renderContext) {
    renderContext.setVertexDrawPaintTransformer(
        new Transformer<CallGraphNode, Paint>() {
          public Paint transform(CallGraphNode node) {
            PickedState<CallGraphNode> pickedState = visualizer.getPickedVertexState();
            if (pickedState.isPicked(node)) {
              return PICKED_COLOR;
            } else {
              return UNPICKED_COLOR;
            }
          }
        });
  }

  protected void setVertexShapeTransformer(
      RenderContext<CallGraphNode, CallGraphLink> renderContext) {
    CallGraphNodeShapeTransformer vertexShapeTransformer =
        new CallGraphNodeShapeTransformer(graph.getJungGraph());
    renderContext.setVertexShapeTransformer(vertexShapeTransformer);
  }

  protected void setVertexLabeler(RenderContext<CallGraphNode, CallGraphLink> renderContext) {
    renderContext.setVertexLabelTransformer(new ToStringLabeller<CallGraphNode>());
    Renderer<CallGraphNode, CallGraphLink> renderer = visualizer.getRenderer();
    BasicVertexLabelRenderer<CallGraphNode, CallGraphLink> labelRenderer =
        new BasicVertexLabelRenderer<CallGraphNode, CallGraphLink>();
    labelRenderer.setPosition(Renderer.VertexLabel.Position.CNTR);
    renderer.setVertexLabelRenderer(labelRenderer);
  }

  protected void setEdgeLabeler(RenderContext<CallGraphNode, CallGraphLink> renderContext) {
    ToStringLabeller<CallGraphLink> toStringLabeller = new ToStringLabeller<CallGraphLink>();
    renderContext.setEdgeLabelTransformer(toStringLabeller);
    Renderer<CallGraphNode, CallGraphLink> renderer = visualizer.getRenderer();
    BasicEdgeLabelRenderer<CallGraphNode, CallGraphLink> labelRenderer =
        new BasicEdgeLabelRenderer<CallGraphNode, CallGraphLink>();
    // labelRenderer.setPosition(Renderer.EdgeLabel.Position.CNTR);
    renderer.setEdgeLabelRenderer(labelRenderer);
  }

  protected JSlider configureIterationSlider(int sliderLimit) {
    iterationSlider = new JSlider(JSlider.HORIZONTAL);
    iterationSlider.setBackground(Color.WHITE);
    iterationSlider.setPreferredSize(new Dimension(210, 50));
    iterationSlider.setPaintTicks(true);
    iterationSlider.setMaximum(sliderLimit);
    iterationSlider.setMinimum(0);
    iterationSlider.setValue(0);
    iterationSlider.setMajorTickSpacing(sliderLimit / 5);
    iterationSlider.setPaintLabels(true);
    iterationSlider.setPaintTicks(true);
    return iterationSlider;
  }

  protected TitledBorder setUpSliderPanel() {
    sliderPanel = new JPanel();
    sliderPanel.setPreferredSize(new Dimension(210, 50));
    int sliderLimit = 50;

    if (graph != null) {
      final Graph<CallGraphNode, CallGraphLink> jungGraph = graph.getJungGraph();
      sliderLimit = jungGraph.getVertexCount();
    }
    configureIterationSlider(sliderLimit);
    sliderPanel.setOpaque(true);
    sliderPanel.add(iterationSlider);
    iterationSlider.setValue(0);
    String eastSize = sliderLabelBase + iterationSlider.getValue();
    TitledBorder sliderBorder = BorderFactory.createTitledBorder(eastSize);
    sliderPanel.setBorder(sliderBorder);
    return sliderBorder;
  }

  public abstract void setUpView(final JavaCallGraph callGraph) throws IOException;

  protected void setUpMouseMode() {
    if (visualizer != null) {
      DefaultModalGraphMouse<?, ?> graphMouse = new DefaultModalGraphMouse<Object, Object>();
      graphMouse.setMode(Mode.PICKING);
      visualizer.setGraphMouse(graphMouse);
    }
  }

  protected void colorCluster(ClusterIfc<CallGraphNode> cluster, Color color) {
    Set<CallGraphNode> vertices = cluster.getElements();

    for (CallGraphNode vertex : vertices) {
      vertexPaints.put(vertex, color);
    }
  }

  /** @return the graph */
  public JavaCallGraph getGraph() {
    return graph;
  }

  /** @return the clusterer */
  public ClustererIfc<?> getClusterer() {
    return clusterer;
  }

  /** @param clusterer2 the clusterer to set */
  public void setClusterer(ClustererIfc<CallGraphNode> clusterer2) {
    this.clusterer = clusterer2;
  }

  /** @return the visualizer */
  public VisualizationViewer<CallGraphNode, CallGraphLink> getVisualizer() {
    return visualizer;
  }

  /** @return the iterationSlider */
  public JSlider getIterationSlider() {
    return iterationSlider;
  }

  protected String groupsToString(StringBuffer buf, Collection<CallGraphNode> clusters) {
    int groupNumber = 1;
    String clusterFormat =
        parameters.getParameter(
            ParameterConstants.CLUSTER_TEXT_FORMAT_KEY, ClusterTextFormatEnum.NEWICK.toString());
    ClusterTextFormatEnum textFormatEnum = ClusterTextFormatEnum.valueOf(clusterFormat);

    for (CallGraphNode node : clusters) {
      buf.append("Group ").append(groupNumber).append(": ");
      buf.append(node.getSimpleName()).append(":\n");
      if (node instanceof CallGraphCluster) {
        CallGraphCluster cluster = (CallGraphCluster) node;

        if (ClusterTextFormatEnum.FLAT.equals(textFormatEnum)) {
          clusterToFlatGroupString(buf, cluster);
        } else {
          cluster.toNestedString(1, buf);
        }
      } else { // Regular CallGraphNode
        buf.append("  ").append(node.getSimpleName()).append("\n");
      }
      groupNumber++;
    }
    String clustersString = buf.toString();
    return clustersString;
  }

  protected void clusterToFlatGroupString(StringBuffer buf, CallGraphCluster cluster) {
    SortedSet<CallGraphNode> subnodes = cluster.getElements();
    ArrayList<CallGraphNode> subNodeList = new ArrayList<CallGraphNode>(subnodes);
    Collections.sort(subNodeList, nodeNameComparator);

    for (CallGraphNode subnode : subNodeList) {
      buf.append("  ").append(subnode.getSimpleName()).append("\n");
    }
  }

  public void setView(ClusteringView clusteringView) {
    view = clusteringView;
  }
}
  public SetupGraphPane() {

    // create a simple graph for the demo
    graph = new SparseMultigraph<Number, Number>();

    this.layout = new StaticLayout<Number, Number>(graph, new Dimension(600, 600));

    vv = new VisualizationViewer<Number, Number>(layout);
    vv.setBackground(Color.white);

    vv.getRenderContext()
        .setVertexLabelTransformer(
            MapTransformer.<Number, String>getInstance(
                LazyMap.<Number, String>decorate(
                    new HashMap<Number, String>(), new ToStringLabeller<Number>())));

    vv.getRenderContext()
        .setEdgeLabelTransformer(
            MapTransformer.<Number, String>getInstance(
                LazyMap.<Number, String>decorate(
                    new HashMap<Number, String>(), new ToStringLabeller<Number>())));

    vv.setVertexToolTipTransformer(vv.getRenderContext().getVertexLabelTransformer());

    final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv);
    add(panel);
    Factory<Number> vertexFactory = new VertexFactory();
    Factory<Number> edgeFactory = new EdgeFactory();

    final EditingModalGraphMouse<Number, Number> graphMouse =
        new EditingModalGraphMouse<Number, Number>(
            vv.getRenderContext(), vertexFactory, edgeFactory);

    // the EditingGraphMouse will pass mouse event coordinates to the
    // vertexLocations function to set the locations of the vertices as
    // they are created
    //        graphMouse.setVertexLocations(vertexLocations);
    vv.setGraphMouse(graphMouse);
    vv.addKeyListener(graphMouse.getModeKeyListener());

    graphMouse.setMode(ModalGraphMouse.Mode.EDITING);

    final ScalingControl scaler = new CrossoverScalingControl();
    JButton plus = new JButton("+");
    plus.addActionListener(
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            scaler.scale(vv, 1.1f, vv.getCenter());
          }
        });
    JButton minus = new JButton("-");
    minus.addActionListener(
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            scaler.scale(vv, 1 / 1.1f, vv.getCenter());
          }
        });

    //        JButton help = new JButton("Help");
    //        help.addActionListener(new ActionListener() {
    //
    //            public void actionPerformed(ActionEvent e) {
    //                JOptionPane.showMessageDialog(vv, instructions);
    //            }});

    AnnotationControls<Number, Number> annotationControls =
        new AnnotationControls<Number, Number>(graphMouse.getAnnotatingPlugin());
    JPanel controls = new JPanel();
    controls.add(plus);
    controls.add(minus);
    JComboBox modeBox = graphMouse.getModeComboBox();
    controls.add(modeBox);
    controls.add(annotationControls.getAnnotationsToolBar());
    // controls.add(help);
    add(controls, BorderLayout.SOUTH);
  }
/**
 * This layout algorithm takes the shapes of the trees into account and performs a non-overlapping
 * layout.
 *
 * @author Ingo Mierswa
 */
public class ShapeBasedTreeLayout<V, E> implements Layout<V, E> {

  private static final int DEFAULT_WIDTH = 70;

  private static final int DEFAULT_HEIGHT = 70;

  private static final int MARGIN = 5;

  private Dimension size = new Dimension(600, 600);

  private Forest<V, E> graph;

  protected Map<V, Point2D> locations =
      LazyMap.decorate(
          new HashMap<V, Point2D>(),
          new Transformer<V, Point2D>() {

            @Override
            public Point2D transform(V arg0) {
              return new Point2D.Double();
            }
          });

  public List<V> getAtomics(V p) {
    List<V> v = new ArrayList<V>();
    getAtomics(p, v);
    return v;
  }

  private void getAtomics(V p, List<V> v) {
    for (V c : graph.getSuccessors(p)) {
      if (graph.getSuccessors(c).size() == 0) {
        v.add(c);
      } else {
        getAtomics(c, v);
      }
    }
  }

  private Collection<V> roots;

  private Transformer<V, Shape> shapeTransformer;

  public ShapeBasedTreeLayout(Forest<V, E> g, Transformer<V, Shape> shapeTransformer) {
    this.graph = g;
    this.roots = getRoots(g);
    this.shapeTransformer = shapeTransformer;
    calculateLocations();
  }

  private Collection<V> getRoots(Forest<V, E> forest) {
    Set<V> roots = new HashSet<V>();
    for (Tree<V, E> tree : forest.getTrees()) {
      roots.add(tree.getRoot());
    }
    return roots;
  }

  public Dimension getCurrentSize() {
    return size;
  }

  private void calculateLocations() {
    double xOffset = 100;
    double yOffset = 30;

    if (roots.size() > 0 && graph != null) {
      for (V v : roots) {
        calculateLocations(v, xOffset, yOffset);
        double currentWidth = calculateWidth(v);
        xOffset += currentWidth;
        xOffset += MARGIN;
      }
    }
  }

  void calculateLocations(V v, double xOffset, double yOffset) {
    double currentWidth = calculateWidth(v);

    setPosition(v, xOffset + currentWidth / 2, yOffset);

    // handle children
    yOffset += DEFAULT_HEIGHT;

    int childrenNum = graph.getSuccessors(v).size();
    if (childrenNum != 0) {
      boolean first = true;
      for (V element : graph.getSuccessors(v)) {
        if (!first) {
          xOffset += MARGIN;
        }

        calculateLocations(element, xOffset, yOffset);

        double totalChildrenWidth = calculateWidth(element);
        xOffset += totalChildrenWidth;

        first = false;
      }
    }
  }

  private double calculateWidth(V v) {
    double childrenWidthSum = 0;
    int childrenNum = graph.getSuccessors(v).size();
    if (childrenNum != 0) {
      boolean first = true;
      for (V element : graph.getSuccessors(v)) {
        if (!first) {
          childrenWidthSum += MARGIN;
        }
        childrenWidthSum += calculateWidth(element);
        first = false;
      }
    }

    double width = DEFAULT_WIDTH;
    if (this.shapeTransformer != null) {
      Shape shape = this.shapeTransformer.transform(v);
      if (shape != null) {
        width = shape.getBounds().getWidth();
      }
    }
    double size = Math.max(width, childrenWidthSum);
    size = Math.max(0, size);
    return size;
  }

  @Override
  public void setSize(Dimension size) {
    this.size = size;
    calculateLocations();
  }

  private void setPosition(V vertex, double x, double y) {
    locations.get(vertex).setLocation(new Point2D.Double(x, y));
  }

  @Override
  public Graph<V, E> getGraph() {
    return graph;
  }

  @Override
  public Dimension getSize() {
    return size;
  }

  @Override
  public void initialize() {}

  @Override
  public boolean isLocked(V v) {
    return false;
  }

  @Override
  public void lock(V v, boolean state) {}

  @Override
  public void reset() {}

  @Override
  public void setGraph(Graph<V, E> graph) {
    if (graph instanceof Forest) {
      this.graph = (Forest<V, E>) graph;
      calculateLocations();
    } else {
      throw new IllegalArgumentException("graph must be a Forest");
    }
  }

  @Override
  public void setInitializer(Transformer<V, Point2D> initializer) {}

  public Point2D getCenter() {
    return new Point2D.Double(size.getWidth() / 2, size.getHeight() / 2);
  }

  @Override
  public void setLocation(V v, Point2D location) {
    locations.get(v).setLocation(location);
  }

  @Override
  public Point2D transform(V v) {
    return locations.get(v);
  }
}
  public GraphEditorDemo() {

    // create a simple graph for the demo
    graph = new SparseMultigraph<Sommet, Number>();

    Transformer<Sommet, Paint> vertexPaint =
        new Transformer<Sommet, Paint>() {
          private final Color vert = Color.GREEN;
          private final Color bleu = Color.BLUE;
          private final Color rouge = Color.RED;

          public Paint transform(Sommet s) {
            if (s.isColoriee()) {
              return rouge;
            } else {
              if (s.proprietaire == 0) {

                return vert;
              } else {
                return bleu;
              }
            }
          }
        };

    this.layout = new StaticLayout<Sommet, Number>(graph, new Dimension(600, 600));

    vv = new VisualizationViewer<Sommet, Number>(layout);
    vv.setBackground(Color.white);

    vv.getRenderContext()
        .setVertexLabelTransformer(
            MapTransformer.<Sommet, String>getInstance(
                LazyMap.<Sommet, String>decorate(
                    new HashMap<Sommet, String>(), new ToStringLabeller<Sommet>())));

    vv.getRenderContext()
        .setEdgeLabelTransformer(
            MapTransformer.<Number, String>getInstance(
                LazyMap.<Number, String>decorate(
                    new HashMap<Number, String>(), new ToStringLabeller<Number>())));

    vv.setVertexToolTipTransformer(vv.getRenderContext().getVertexLabelTransformer());

    vv.getRenderContext().setVertexFillPaintTransformer(vertexPaint);

    Container content = getContentPane();
    final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv);
    content.add(panel);
    Factory<Sommet> vertexFactory = new VertexFactory();
    Factory<Number> edgeFactory = new EdgeFactory();

    final EditingModalGraphMouse<Sommet, Number> graphMouse =
        new EditingModalGraphMouse<Sommet, Number>(
            vv.getRenderContext(), vertexFactory, edgeFactory);

    // the EditingGraphMouse will pass mouse event coordinates to the
    // vertexLocations function to set the locations of the vertices as
    // they are created
    //        graphMouse.setVertexLocations(vertexLocations);
    vv.setGraphMouse(graphMouse);
    vv.addKeyListener(graphMouse.getModeKeyListener());

    graphMouse.setMode(ModalGraphMouse.Mode.CREATION);

    final ScalingControl scaler = new CrossoverScalingControl();

    JButton plus = new JButton("+");
    plus.addActionListener(
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            scaler.scale(vv, 1.1f, vv.getCenter());
          }
        });
    JButton minus = new JButton("-");
    minus.addActionListener(
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            scaler.scale(vv, 1 / 1.1f, vv.getCenter());
          }
        });

    JToggleButton jtb = new JToggleButton("Joueur 1");
    jtb.addItemListener(
        new ItemListener() {
          public void itemStateChanged(ItemEvent ev) {
            if (ev.getStateChange() == ItemEvent.SELECTED) {
              joueurcourant = 1;

            } else if (ev.getStateChange() == ItemEvent.DESELECTED) {
              joueurcourant = 0;
            }
          }
        });

    JToggleButton jtf = new JToggleButton("Final");
    jtf.addItemListener(
        new ItemListener() {
          public void itemStateChanged(ItemEvent ev) {
            if (ev.getStateChange() == ItemEvent.SELECTED) {
              etatfinal = true;

            } else if (ev.getStateChange() == ItemEvent.DESELECTED) {
              etatfinal = false;
            }
          }
        });

    JButton att = new JButton("Attracteur Accessibilité");
    minus.addActionListener(
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            ArrayList<Sommet> vertices = (ArrayList<Sommet>) graph.getVertices();
            ArrayList<Sommet> finaux = new ArrayList<Sommet>();
            for (Sommet s : vertices) {
              if (s.isFinal) finaux.add(s);
            }
            colorierAttracteur(finaux, graph.getVertexCount());
          }
        });

    AnnotationControls<Sommet, Number> annotationControls =
        new AnnotationControls<Sommet, Number>(graphMouse.getAnnotatingPlugin());
    JPanel controls = new JPanel();
    controls.add(plus);
    controls.add(minus);
    JComboBox modeBox = graphMouse.getModeComboBox();
    controls.add(modeBox);
    controls.add(jtb);
    controls.add(jtf);
    controls.add(att);
    // controls.add(annotationControls.getAnnotationsToolBar());
    content.add(controls, BorderLayout.SOUTH);
  }