public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g;

    currentX = leftMargin;
    currentY = topMargin;

    // Draw the links

    for (int i = 0; i < linkLines.length; i++) {
      if (weights[i].isActive()) {
        g2.setPaint(weights[i].getColor());
        g2.draw(linkLines[i]);
      }
    }

    g2.setPaint(Color.black);

    // Draw the input neurons
    g2.drawString("Inputs", (float) currentX, (float) currentY);
    currentY += titleSpace;

    for (int i = 0; i < genome.getInputs(); i++) {
      g2.drawImage(inputNeuron, (int) currentX, (int) currentY, null);
      currentY += space;
    }

    // Draw the hidden Neurons
    currentX += space;
    currentY = topMargin;
    g2.drawString("Hidden Layers", (float) currentX, (float) currentY);

    for (int i = 0; i < genome.getHiddenLayers(); i++) {
      currentY = topMargin + titleSpace;
      for (int j = 0; j < genome.getNeuronsInHiddenLayer(); j++) {
        g2.drawImage(hiddenNeuron, (int) currentX, (int) currentY, null);
        currentY += space;
      }
      currentX += space;
    }

    // Draw the output neurons
    currentY = topMargin;
    g2.drawString("Outputs", (float) currentX, (float) currentY);
    currentY += titleSpace;

    for (int i = 0; i < genome.getOutputs(); i++) {
      g2.drawImage(outputNeuron, (int) currentX, (int) currentY, null);
      currentY += space;
    }

    // Draw the links

    for (int i = 0; i < linkLines.length; i++) {
      if (weights[i].isActive()) {
        g2.setPaint(weights[i].getColor());
        g2.draw(linkLines[i]);
      }
    }
  }
  /**
   * Creates a new NetworkFrame
   *
   * @param _t The title of the diagram
   * @param _g The genome of the network
   * @param _w The weights of the network
   */
  public NetworkFrame(String _t, Genome _g, Link[] _w) {
    setTitle(_t);

    int width = 175 + _g.getHiddenLayers() * 82;
    int height = 100 + _g.getNeuronsInHiddenLayer() * 78;
    setSize(width, height);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    NetworkPanel panel = new NetworkPanel(_g, _w);
    Container contentPane = getContentPane();
    contentPane.add(panel);
  }
  /**
   * Creates a new NetworkPanel
   *
   * @param _g The genome of the network
   * @param _w The weights of the network
   */
  public NetworkPanel(Genome _g, Link[] _w) {
    setBackground(Color.white);

    genome = _g;
    weights = _w;

    // Tracker for the images
    tracker.addImage(inputNeuron, 0);
    tracker.addImage(hiddenNeuron, 1);
    tracker.addImage(outputNeuron, 2);
    try {
      tracker.waitForAll();
    } catch (InterruptedException e) {
    }

    // Create the lines for the links between the layers
    // The array of lines is actually complete (as for a fully connected network)
    // The loop in paintComponent decideds whether to draw the line or not.
    linkLines = new Line2D.Double[weights.length];
    int counter = 0;
    double fromX = leftMargin + inW;
    double fromY = topMargin + titleSpace + iconHeight / 2.0;
    double toX = leftMargin + space;
    double toY = fromY;

    // Create the lines for the links between the first hidden layer and the input layer
    for (int i = 0;
        i < genome.getNeuronsInHiddenLayer();
        i++) // Loop through the neurons in 1st hidden layer
    {
      fromY = topMargin + titleSpace + iconHeight / 2.0;
      for (int j = 0; j < genome.getInputs(); j++) // Loop through the neurons in the input layer
      {
        linkLines[counter] = new Line2D.Double(fromX, fromY, toX, toY);
        fromY += space;
        counter++;
      }
      toY += space;
    }

    // Create the lines for the links between the hidden layers
    fromX += space;
    fromY = topMargin + titleSpace + iconHeight / 2.0;
    toX = fromX + space - hW;
    toY = fromY;
    for (int i = 0; i < genome.getHiddenLayers() - 1; i++) // Loop across the hidden layers
    {
      fromY = topMargin + titleSpace + iconHeight / 2.0;
      toY = fromY;
      for (int j = 0; j < genome.getNeuronsInHiddenLayer(); j++) // Loop down the 'to' hidden layer
      {
        fromY = topMargin + titleSpace + iconHeight / 2.0;
        for (int k = 0;
            k < genome.getNeuronsInHiddenLayer();
            k++) // Loop down the 'from' hidden layer
        {
          linkLines[counter] = new Line2D.Double(fromX, fromY, toX, toY);
          fromY += space;
          counter++;
        }
        toY += space;
      }
      fromX += space;
      toX = fromX + space - hW;
    }

    // Create the lines for the links between the output layer and the final hidden layer
    fromX = leftMargin + space * genome.getHiddenLayers() + hW;
    fromY = topMargin + titleSpace + iconHeight / 2.0;
    toX = leftMargin + space * (genome.getHiddenLayers() + 1);
    toY = fromY;
    for (int i = 0; i < genome.getOutputs(); i++) // Loop through the outputs
    {
      fromY = topMargin + titleSpace + 14.0;
      for (int j = 0;
          j < genome.getNeuronsInHiddenLayer();
          j++) // Loop through the neurons in the final hidden layer
      {
        linkLines[counter] = new Line2D.Double(fromX, fromY, toX, toY);
        fromY += space;
        counter++;
      }
      toY += space;
    }
  }