/** Create a node at the most recent popup location */
  private void createNode(int x, int y) {
    QueryNode qn = queryGraph.createNode();
    Node node = new Node(this, qn);

    // make it the head node if it is currently the only node
    if (queryGraph.getNumNodes() == 1) {
      node.setHeadNode(true);
      setHeadNode(node);
    }

    // place on the screen
    node.setLocation(x, y);
    this.add(node);
    this.repaint();

    // add the popup
    NodeListener listener = new NodeListener(node, this);
    node.addMouseListener(listener);
    node.addMouseMotionListener(listener);

    // select this new node
    selectNode(node);
    fireEvent(node, GRAPH_CHANGED);

    System.out.println(qn.label);
  }
  private void deleteGraphEdge(Edge edge) {
    // make sure we aren't deleting a null edge
    assert (edge != null);
    assert (edge.type == Edge.Type.GRAPH_EDGE);

    // deselect if necessary
    if (edge == selectedItem) selectEdge(null);

    queryGraph.removeEdge(edge.getQueryEdge());
    graphEdges.remove(edge);

    // signal deletion
    fireEvent(edge, GRAPH_CHANGED);
  }
  private Edge createEdge(Node n1, Node n2, boolean select) {
    QueryEdge qe = queryGraph.createEdge(n1.getQueryNode(), n2.getQueryNode());
    if (qe == null) return null;

    Edge edge = new Edge(n1, n2, qe);
    graphEdges.add(edge);

    // select the edge after creating it
    if (select) selectEdge(edge);

    fireEvent(edge, GRAPH_CHANGED);

    System.out.println("Created edge");
    return edge;
  }
  /**
   * deletes the selected node, usually
   *
   * @param node
   * @param b
   */
  public void deleteNode(Node node, boolean forceHeadNodeDeletion) {
    assert (node != null);
    if (node == headNode && !forceHeadNodeDeletion) return;

    // delete all of the connected edges
    List<QueryEdge> adjacentEdges = node.getQueryNode().getEdges();
    for (QueryEdge e : adjacentEdges) deleteGraphEdge(e.getOwner());

    // deselect the node if already selected
    if (node == selectedItem) selectNode(null);

    // delete the node from the query graph
    queryGraph.removeNode(node.getQueryNode());

    // remove the component from the panel
    this.remove(node);

    // signal deletion
    fireEvent(node, GRAPH_CHANGED);
  }
 public void clearGraph() {
   List<QueryNode> nodeList = queryGraph.getNodes();
   for (QueryNode n : nodeList) deleteNode(n.getOwner(), true);
 }
  /*
   * Get the text query represented by the underlying graph
   */
  public String getQuery() {
    if (queryGraph.getNumNodes() == 0) return "";

    return queryGraph.toTregexQuery(headNode.getQueryNode());
  }
 private void updatePopupMenu() {
   addEdgeItem.setEnabled(queryGraph.getNumNodes() > 1);
   if (targetNode != null) deleteNodeItem.setEnabled(!targetNode.isHeadNode());
 }