/*.................................................................................................................*/
 public Snapshot getSnapshot(MesquiteFile file) {
   Snapshot temp = new Snapshot();
   temp.addLine("setRunningFilePath " + ParseUtil.tokenize(runningFilePath));
   if (outputFilePaths != null) {
     String files = " ";
     for (int i = 0; i < outputFilePaths.length; i++) {
       files += " " + ParseUtil.tokenize(outputFilePaths[i]);
     }
     temp.addLine("setOutputFilePaths " + files);
   }
   return temp;
 }
 /*.................................................................................................................*/
 public void fromString(String description, MesquiteInteger stringPos, int format) {
   hasDefaultValues = false;
   ParseUtil.getToken(description, stringPos); // RMatrix
   ParseUtil.getToken(description, stringPos); // =
   ParseUtil.getToken(description, stringPos); // (
   for (int i = 0; i < getNumStates(); i++) {
     String s = ParseUtil.getToken(description, stringPos);
     if (s.equalsIgnoreCase(")") || StringUtil.blank(s)) return;
     setStateFreq(i, MesquiteDouble.fromString(s));
   }
   checkNormality(getStateFrequencies());
 }
  /*.................................................................................................................*/
  public Object doCommand(String commandName, String arguments, CommandChecker checker) {
    Tree trt = treeDisplay.getTree();
    MesquiteTree t = null;
    if (trt instanceof MesquiteTree) t = (MesquiteTree) trt;
    if (checker.compare(
        this.getClass(),
        "Adjust tool has touched branch",
        "[branch number][x coordinate touched][y coordinate touched][modifiers]",
        commandName,
        "touchedPositionAdjust")) {
      if (t == null) return null;
      MesquiteInteger io = new MesquiteInteger(0);
      int node = MesquiteInteger.fromString(arguments, io);
      int x = MesquiteInteger.fromString(arguments, io);
      int y = MesquiteInteger.fromString(arguments, io);
      String mod = ParseUtil.getRemaining(arguments, io);

      Point newOnLine = treeDisplay.getTreeDrawing().projectionOnLine(node, x, y);
      originalX = newOnLine.x;
      originalY = newOnLine.y;
      // lastX= newOnLine.x;
      // lastY = newOnLine.y;
      Graphics g = null;
      if (GraphicsUtil.useXORMode(null, false)) {
        g = treeDisplay.getGraphics();
        g.setXORMode(Color.white);
        g.setColor(Color.red);
      }
      // double bX = treeDisplay.getTreeDrawing().lineBaseX[node];
      // double bY = treeDisplay.getTreeDrawing().lineBaseY[node];
      // Math.sqrt((originalY-bY)*(originalY-bY) + (originalX-bX)*(originalX-bX));
      lastBL = tree.getBranchLength(node);
      double shortestAbove = MesquiteDouble.unassigned;
      for (int daughter = t.firstDaughterOfNode(node);
          t.nodeExists(daughter);
          daughter = t.nextSisterOfNode(daughter))
        shortestAbove = MesquiteDouble.minimum(shortestAbove, tree.getBranchLength(daughter));
      if (shortestAbove == MesquiteDouble.unassigned) upperLimit = MesquiteDouble.infinite;
      else if (MesquiteDouble.isCombinable(lastBL)) upperLimit = shortestAbove + lastBL;
      else upperLimit = shortestAbove + 1.0;
      int ibX = treeDisplay.getTreeDrawing().lineBaseX[node];
      int ibY = treeDisplay.getTreeDrawing().lineBaseY[node];
      lastX = treeDisplay.getTreeDrawing().lineTipX[node];
      lastY = treeDisplay.getTreeDrawing().lineTipY[node];
      if (GraphicsUtil.useXORMode(null, false)) {
        drawThickLine(g, ibX, ibY, lastX, lastY);
        for (int daughter = t.firstDaughterOfNode(node);
            t.nodeExists(daughter);
            daughter = t.nextSisterOfNode(daughter))
          drawThickLine(
              g,
              treeDisplay.getTreeDrawing().lineTipX[daughter],
              treeDisplay.getTreeDrawing().lineTipY[daughter],
              lastX,
              lastY);
        g.fillOval(
            lastX - ovalRadius,
            lastY - ovalRadius,
            ovalRadius + ovalRadius,
            ovalRadius + ovalRadius);
        try {
          g.drawString(MesquiteDouble.toString(lastBL), lastX + 10, lastY);
        } catch (InternalError e) { // workaround for bug on windows java 1.7.
        } catch (Throwable e) {
        }
        lineOn = true;
        g.dispose();
      }
    } else if (checker.compare(
        this.getClass(),
        "Adjust tool has been dropped",
        "[branch number][x coordinate dropped][y coordinate dropped]",
        commandName,
        "droppedPositionAdjust")) {
      if (t == null) return null;
      if (editorOn) return null;
      MesquiteInteger io = new MesquiteInteger(0);
      int node = MesquiteInteger.fromString(arguments, io);
      int x = MesquiteInteger.fromString(arguments, io);
      int y = MesquiteInteger.fromString(arguments, io);
      if (lineOn) {
        Point newOnLine = treeDisplay.getTreeDrawing().projectionOnLine(node, x, y);
        double bX = treeDisplay.getTreeDrawing().lineBaseX[node];
        double bY = treeDisplay.getTreeDrawing().lineBaseY[node];
        double tX = treeDisplay.getTreeDrawing().lineTipX[node];
        double tY = treeDisplay.getTreeDrawing().lineTipY[node];
        double lengthLine =
            Math.sqrt((originalY - bY) * (originalY - bY) + (originalX - bX) * (originalX - bX));
        double bL;
        if (lengthLine != 0) {
          double extension =
              Math.sqrt(
                      (newOnLine.y - bY) * (newOnLine.y - bY)
                          + (newOnLine.x - bX) * (newOnLine.x - bX))
                  / lengthLine;
          if (t.getBranchLength(node) == 0 || t.branchLengthUnassigned(node)) bL = extension;
          else bL = t.getBranchLength(node) * extension;
        } else bL = 1;

        if (bL > upperLimit) bL = upperLimit;
        else if (bL < lowerLimit) bL = lowerLimit;
        double oldBL = t.getBranchLength(node);
        if (!MesquiteDouble.isCombinable(oldBL)) oldBL = 1.0;
        t.setBranchLength(node, bL, false);
        double difference = oldBL - t.getBranchLength(node);
        for (int daughter = t.firstDaughterOfNode(node);
            t.nodeExists(daughter);
            daughter = t.nextSisterOfNode(daughter))
          if (MesquiteDouble.isCombinable(t.getBranchLength(daughter)))
            t.setBranchLength(daughter, t.getBranchLength(daughter) + difference, false);
        t.notifyListeners(this, new Notification(MesquiteListener.BRANCHLENGTHS_CHANGED));
        Graphics g = treeDisplay.getGraphics();
        g.setPaintMode();
        g.dispose();
        treeDisplay.pleaseUpdate(true);
        lineOn = false;
      }
    } else if (checker.compare(
        this.getClass(),
        "Adjust tool is being dragged",
        "[branch number][x coordinate][y coordinate]",
        commandName,
        "draggedPositionAdjust")) {
      if (t == null) return null;
      if (editorOn) return null;
      MesquiteInteger io = new MesquiteInteger(0);
      int node = MesquiteInteger.fromString(arguments, io);
      int x = MesquiteInteger.fromString(arguments, io);
      int y = MesquiteInteger.fromString(arguments, io);
      if (lineOn) {
        Point newOnLine = treeDisplay.getTreeDrawing().projectionOnLine(node, x, y);
        // WARNING":  This shouldn't result in length increase if simple click and release with no
        // drag; must subtract original X, Y
        Graphics g = null;
        if (GraphicsUtil.useXORMode(null, false)) {
          g = treeDisplay.getGraphics();
          g.setXORMode(Color.white);
          g.setColor(Color.red);
        }
        // g.fillOval(lastX-ovalRadius, lastY-ovalRadius, ovalRadius + ovalRadius, ovalRadius +
        // ovalRadius);
        // g.fillOval(newOnLine.x-ovalRadius, newOnLine.y -ovalRadius, ovalRadius + ovalRadius,
        // ovalRadius + ovalRadius);

        // g.drawLine(originalX, originalY, lastX, lastY);
        // g.drawLine(originalX, originalY, newOnLine.x, newOnLine.y);

        //				if decreasing, & unassigned involved: push unassigned down and assign values to
        // unassigned above; if increasing, push unassigne up
        int ibX = treeDisplay.getTreeDrawing().lineBaseX[node];
        int ibY = treeDisplay.getTreeDrawing().lineBaseY[node];
        int itX = treeDisplay.getTreeDrawing().lineTipX[node];
        int itY = treeDisplay.getTreeDrawing().lineTipY[node];

        double bX = ibX;
        double bY = ibY;
        double tX = itX;
        double tY = itY;
        double lengthLine =
            Math.sqrt((originalY - bY) * (originalY - bY) + (originalX - bX) * (originalX - bX));
        if (lengthLine != 0) {
          if (GraphicsUtil.useXORMode(null, false)) {
            if (MesquiteTrunk.isMacOSX()
                && MesquiteTrunk.getJavaVersionAsDouble() >= 1.5
                && MesquiteTrunk.getJavaVersionAsDouble() < 1.6) // due to a JVM bug
            g.fillRect(lastX, lastY - 20, 100, 20);
            g.drawString(MesquiteDouble.toString(lastBL), lastX + 10, lastY);
            if (MesquiteTrunk.isMacOSX()
                && MesquiteTrunk.getJavaVersionAsDouble() >= 1.5
                && MesquiteTrunk.getJavaVersionAsDouble() < 1.6) // due to a JVM bug
            g.fillRect(lastX, lastY - 20, 100, 20);
          }
          double extension =
              Math.sqrt(
                      (newOnLine.y - bY) * (newOnLine.y - bY)
                          + (newOnLine.x - bX) * (newOnLine.x - bX))
                  / lengthLine;
          double bL;
          if (t.getBranchLength(node) == 0 || t.branchLengthUnassigned(node)) bL = extension;
          else bL = t.getBranchLength(node) * extension;
          if (bL > upperLimit) {
            bL = upperLimit;
            if (t.getBranchLength(node) == 0 || t.branchLengthUnassigned(node))
              extension = upperLimit;
            else extension = upperLimit / t.getBranchLength(node);
          } else if (bL < lowerLimit) {
            bL = lowerLimit;
            if (t.getBranchLength(node) == 0 || t.branchLengthUnassigned(node))
              extension = lowerLimit;
            else extension = lowerLimit / t.getBranchLength(node);
          }
          lastBL = bL;
          if (GraphicsUtil.useXORMode(null, false)) {
            drawThickLine(g, ibX, ibY, lastX, lastY);
            for (int daughter = t.firstDaughterOfNode(node);
                t.nodeExists(daughter);
                daughter = t.nextSisterOfNode(daughter))
              drawThickLine(
                  g,
                  treeDisplay.getTreeDrawing().lineTipX[daughter],
                  treeDisplay.getTreeDrawing().lineTipY[daughter],
                  lastX,
                  lastY);
            g.fillOval(
                lastX - ovalRadius,
                lastY - ovalRadius,
                ovalRadius + ovalRadius,
                ovalRadius + ovalRadius);
          }
          int newX = ibX + (int) (extension * (tX - bX));
          int newY = ibY + (int) (extension * (tY - bY));
          if (GraphicsUtil.useXORMode(null, false)) {
            g.drawString(MesquiteDouble.toString(bL), newX + 10, newY);
            drawThickLine(g, ibX, ibY, newX, newY);
            for (int daughter = t.firstDaughterOfNode(node);
                t.nodeExists(daughter);
                daughter = t.nextSisterOfNode(daughter))
              drawThickLine(
                  g,
                  treeDisplay.getTreeDrawing().lineTipX[daughter],
                  treeDisplay.getTreeDrawing().lineTipY[daughter],
                  newX,
                  newY);
            g.fillOval(
                newX - ovalRadius,
                newY - ovalRadius,
                ovalRadius + ovalRadius,
                ovalRadius + ovalRadius);
          }
          lastX = newX;
          lastY = newY;
        }

        // lastX= newOnLine.x;
        // lastY = newOnLine.y;
      }
    }
    return null;
  }
 /*.................................................................................................................*/
 public Snapshot getSnapshot(MesquiteFile file) {
   Snapshot temp = new Snapshot();
   temp.addLine("setUsername " + ParseUtil.tokenize(username));
   return temp;
 }