// Close the window when the close box is clicked
  public void windowClosing(java.awt.event.WindowEvent e) {
    // check for various types of dirty - first table data not written back
    if (cvModel.decoderDirty() || variableModel.decoderDirty()) {
      if (JOptionPane.showConfirmDialog(
              null,
              "Some changes have not been written to the decoder. They will be lost. Close window?",
              "choose one",
              JOptionPane.OK_CANCEL_OPTION)
          == JOptionPane.CANCEL_OPTION) {
        return;
      }
    }
    if (variableModel.fileDirty()) {
      if (JOptionPane.showConfirmDialog(
              null,
              "Some changes have not been written to a configuration file. Close window?",
              "choose one",
              JOptionPane.OK_CANCEL_OPTION)
          == JOptionPane.CANCEL_OPTION) {
        return;
      }
    }

    modePane.dispose();
    // OK, close
    super.windowClosing(e);
  }
  @edu.umd.cs.findbugs.annotations.SuppressWarnings(
      value = "REC_CATCH_EXCEPTION") // dead class doesn't need this fixed right now
  void writeFile() {
    log.warn(
        "SymbolicProgFrame writeFile invoked - is this still right, or should the LocoFile method be used?");
    log.warn("Note use of VersionID attribute...");
    try {
      // get the file
      int retVal = fco.showSaveDialog(this);
      // handle selection or cancel
      if (retVal != JFileChooser.APPROVE_OPTION) {
        return; // leave early
      }
      File file = fco.getSelectedFile();

      // This is taken in large part from "Java and XML" page 368
      // create root element
      Element root = new Element("locomotive-config");
      Document doc =
          jmri.jmrit.XmlFile.newDocument(
              root, jmri.jmrit.XmlFile.dtdLocation + "locomotive-config.dtd");

      // add XSLT processing instruction
      // <?xml-stylesheet type="text/xsl" href="XSLT/locomotive.xsl"?>
      java.util.Map<String, String> m = new java.util.HashMap<String, String>();
      m.put("type", "text/xsl");
      m.put("href", jmri.jmrit.XmlFile.xsltLocation + "locomotive.xsl");
      ProcessingInstruction p = new ProcessingInstruction("xml-stylesheet", m);
      doc.addContent(0, p);

      // add top-level elements
      Element values;
      root.addContent(
          new Element("locomotive") // locomotive values are first item
              .setAttribute("roadNumber", locoRoadNumber.getText())
              .setAttribute("roadName", locoRoadName.getText())
              .setAttribute("mfg", locoMfg.getText())
              .setAttribute("model", locoModel.getText())
              .addContent(
                  new Element("decoder")
                      .setAttribute("model", decoderModel.getText())
                      .setAttribute("mfg", decoderMfg.getText())
                      .setAttribute("versionID", "")
                      .setAttribute("mfgID", ""))
              .addContent(values = new Element("values")));

      // Append a decoderDef element to values
      Element decoderDef;
      values.addContent(decoderDef = new Element("decoderDef"));
      // add the variable values to the decoderDef Element
      for (int i = 0; i < variableModel.getRowCount(); i++) {
        decoderDef.addContent(
            new Element("varValue")
                .setAttribute("item", variableModel.getLabel(i))
                .setAttribute("value", variableModel.getValString(i)));
      }
      // add the CV values to the values Element
      for (int i = 0; i < cvModel.getRowCount(); i++) {
        values.addContent(
            new Element("CVvalue")
                .setAttribute("name", cvModel.getName(i))
                .setAttribute("value", cvModel.getValString(i)));
      }

      // write the result to selected file
      java.io.FileOutputStream o = new java.io.FileOutputStream(file);
      try {
        XMLOutputter fmt = new XMLOutputter();
        fmt.setFormat(
            Format.getPrettyFormat()
                .setLineSeparator(System.getProperty("line.separator"))
                .setTextMode(Format.TextMode.PRESERVE));
        fmt.output(doc, o);
      } finally {
        o.close();
      }

      // mark file as OK
      variableModel.setFileDirty(false);
    } catch (Exception e) {
      log.error(e.getLocalizedMessage(), e);
    }
  }
  void processLocoFile(Element loco) {
    // load the name et al
    locoRoadName.setText(loco.getAttributeValue("roadName"));
    locoRoadNumber.setText(loco.getAttributeValue("roadNumber"));
    locoMfg.setText(loco.getAttributeValue("mfg"));
    locoModel.setText(loco.getAttributeValue("model"));
    // load the variable definitions for the decoder
    Element decoder = loco.getChild("decoder");
    if (decoder != null) {
      // get the file name
      String mfg = decoder.getAttribute("mfg").getValue();
      String model = decoder.getAttribute("model").getValue();
      String filename = "xml" + File.separator + mfg + "_" + model + ".xml";
      if (log.isDebugEnabled()) {
        log.debug("will read decoder info from " + filename);
      }
      readAndParseConfigFile(new File(filename));
      if (log.isDebugEnabled()) {
        log.debug("finished processing decoder file for loco file");
      }
    } else {
      log.error("No decoder element found in config file");
    }

    // get the CVs and load
    Element values = loco.getChild("values");
    if (values != null) {
      // get the CV values and load
      List<Element> varList = values.getChildren("CVvalue");
      if (log.isDebugEnabled()) {
        log.debug("Found " + varList.size() + " CVvalues");
      }

      for (int i = 0; i < varList.size(); i++) {
        // locate the row
        if (((varList.get(i))).getAttribute("name") == null) {
          if (log.isDebugEnabled()) {
            log.debug(
                "unexpected null in name "
                    + ((varList.get(i)))
                    + " "
                    + ((varList.get(i))).getAttributes());
          }
          break;
        }
        if (((varList.get(i))).getAttribute("value") == null) {
          if (log.isDebugEnabled()) {
            log.debug(
                "unexpected null in value "
                    + ((varList.get(i)))
                    + " "
                    + ((varList.get(i))).getAttributes());
          }
          break;
        }

        String name = ((varList.get(i))).getAttribute("name").getValue();
        String value = ((varList.get(i))).getAttribute("value").getValue();
        if (log.isDebugEnabled()) {
          log.debug("CV: " + i + "th entry, CV number " + name + " has value: " + value);
        }

        CvValue cvObject = cvModel.allCvMap().get(name);
        cvObject.setValue(Integer.valueOf(value).intValue());
        cvObject.setState(CvValue.FROMFILE);
      }
      variableModel.configDone();
    } else {
      log.error("no values element found in config file; CVs not configured");
      return;
    }
    // get the variable values and load
    Element decoderDef = values.getChild("decoderDef");
    if (decoderDef != null) {
      List<Element> varList = decoderDef.getChildren("varValue");
      if (log.isDebugEnabled()) {
        log.debug("Found " + varList.size() + " varValues");
      }

      for (int i = 0; i < varList.size(); i++) {
        // locate the row
        Attribute itemAttr = null;
        if ((itemAttr = varList.get(i).getAttribute("item")) == null) {
          if (log.isDebugEnabled()) {
            log.debug("unexpected null in item " + varList.get(i));
          }
          break;
        }
        if ((itemAttr = varList.get(i).getAttribute("name")) == null) {
          if (log.isDebugEnabled()) {
            log.debug("unexpected null in name " + varList.get(i));
          }
          break;
        }
        String item = itemAttr.getValue();

        if (((varList.get(i))).getAttribute("value") == null) {
          if (log.isDebugEnabled()) {
            log.debug("unexpected null in value " + ((varList.get(i))));
          }
          break;
        }
        String value = ((varList.get(i))).getAttribute("value").getValue();

        if (log.isDebugEnabled()) {
          log.debug("Variable " + i + " is " + item + " value: " + value);
        }

        int row;
        for (row = 0; row < variableModel.getRowCount(); row++) {
          if (variableModel.getLabel(row).equals(item)) {
            break;
          }
        }
        if (log.isDebugEnabled()) {
          log.debug("Variable " + item + " is row " + row);
        }
        if (!value.equals("")) { // don't set if no value was stored
          variableModel.setIntValue(row, Integer.valueOf(value).intValue());
        }
        variableModel.setState(row, VariableValue.FROMFILE);
      }
      variableModel.configDone();
    } else {
      log.error("no decoderDef element found in config file");
    }

    // the act of loading values marks as dirty, but we're actually in synch
    variableModel.setFileDirty(false);
  }