/*
 * @(#)KMTDesktop.java	0.2 2001/04/03
 *
 * Copyright 2001 by Carnegie Mellon, All rights reserved.
 */

package kmt;
import java.io.*;
import javax.help.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import java.awt.event.*;
import java.awt.*;
import java.util.*;
import java.beans.*;

import edu.cmu.lti.kantoo.analyzer.Issue;
import edu.cmu.lti.kantoo.network.*;
import edu.cmu.lti.kantoo.shared.*;

import java.net.*;

/**
 * KMTDesktop represents the GUI for the KMT
 *
 * @author  David Svoboda & Eric Nyberg
 * @version 0.2 2001/04/03
 */
public class KMTDesktop extends JFrame {

  /**
   * A logger to record Worker executions
   */
  private java.util.logging.Logger logger = Log.getLogger(KMTDesktop.class);


  // STATIC CLASS VARIABLES

  private static final Border    emptyBorder      = BorderFactory.createEmptyBorder(0,2,2,2);

  private Font labelRegFont;

  // CLASS VARIABLES
  private Vector                 internalFrames;
  private IconPolice             iconPolice;
  private DesktopManager         manager;
  private PropertyManager        properties = new PropertyManager(KMTDesktop.class);
    // Load properties from kmt.properties.

  private JDesktopPane           desk;
  private JLabel                 statusLabel;
  private JLabel                 analyzerStatus;
  private JLabel                 generatorStatus;
  private JLabel                 versionerStatus;
  private JTextField             inputTextField;
  JTextArea              traceTextArea  = newTextArea("trace");
  private JTextArea              outputTextArea;
  private JInternalFrame         optionFrame;
  private JInternalFrame         traceFrame;

  private KMTModuleTraceListener anaModuleListener;
  private KMTModuleTraceListener genModuleListener;
  private KMTRuleTraceListener   anaRuleListener;
  private KMTRuleTraceListener   genRuleListener;
  private KMTInputListener       inputListener;
  private KMTListListener        listListener;

  private EventHandler           eventHandler;

  private JLabel analyzerLabel;
  private JLabel generatorLabel;
  private JLabel versionerLabel;

  /**
   * The suite list of sentences
   */
  JList suiteList = null;

  /**
   * @return properties
   */
  public PropertyManager getProperties() {return properties;}


  // CONSTRUCTOR
  public KMTDesktop(String title) {this( title, null);}

  public KMTDesktop(String title, String suiteFile) {
    super(title);

    labelRegFont = Font.decode( properties.get("font"));

    // Window & Icon Managers.
    internalFrames = new Vector();
    manager = new DefaultDesktopManager(); // do we want SampleDesktopMgr();
    iconPolice = new IconPolice();

    // Desktop.
    desk = new JDesktopPane();
    desk.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
    desk.setBackground(Color.gray);
    desk.setDesktopManager(manager);

    // Status Bar.
    statusLabel = new JLabel("");
    statusLabel.setFont(labelRegFont);
    statusLabel.setOpaque(true);

    JPanel panel = new JPanel();
    panel.setLayout(new java.awt.BorderLayout());
    panel.add("North", statusLabel);
    panel.add("Center", desk);
    getContentPane().add( panel);

    // install the command table
    commands = PropertyActionMap.createActionMap( defaultActions);

    // Menu Bar.
    JMenuBar mb = new JMenuBar();
    new PropertyActionMap( properties, "menubar", commands).addtoMenubar( mb);
    setJMenuBar(mb);

    // Event Handler.
    eventHandler = new EventHandler(this);
    new Thread( eventHandler).start();

    // Listeners (require EventHandler).
    anaModuleListener = new KMTModuleTraceListener( eventHandler.getAnalyzer());
    genModuleListener = new KMTModuleTraceListener( eventHandler.getGenerator());
    anaRuleListener   = new KMTRuleTraceListener( eventHandler.getAnalyzer());
    genRuleListener   = new KMTRuleTraceListener( eventHandler.getGenerator());
    inputListener     = new KMTInputListener();
    listListener      = new KMTListListener();

    // Internal Frames (require Listeners).
    addFrame("User_Input", createInputPanel(), true);
    traceTextArea.setFont(labelRegFont);
    traceFrame = addFrame("Trace_Output", createTracePanel( traceTextArea), true);
    outputTextArea = newTextArea("output");
    outputTextArea.setFont(labelRegFont);
    addFrame("System_Output", createTracePanel( outputTextArea), true);
    addFrame("Suite", createSuitePanel( suiteFile), true);
    optionFrame = addFrame("Options", createOptionPanel(), false);
    try { 
      // optionFrame.setIcon(true); 
      traceFrame.setIcon(true); 
    } catch (Exception e) {}

    setAnalyzerStatus("OK");
    setGeneratorStatus("OK");
    setStatus("Ready.");
  }

  private Dimension getDimensionProperty(String label) {
    return new Dimension( Integer.parseInt( properties.get(label+".width")),
			  Integer.parseInt( properties.get(label+".height")));
  }

  private JTextArea newTextArea(String label) {
    return new JTextArea( Integer.parseInt( properties.get(label+".rows")),
			  Integer.parseInt( properties.get(label+".columns")));
  }


  // ACCESSER / SETTER METHODS.

  public synchronized void setStatus(final String s) {
    SwingUtilities.invokeLater(new Runnable() {
	public void run() {
	  statusLabel.setText(" "+s);
	}});
  }

  public synchronized void setInput(String s) {
    inputTextField.setText(s);
  }
    
  private void setAnalyzerInfo(String host, String port) {
  }

  private void setAnalyzerStatus(String status) {
    analyzerStatus.setText(status);
  }

  private void setGeneratorInfo(String host, String port) {
  }

  private void setGeneratorStatus(String status) {
    generatorStatus.setText(status);
  }

  public void appendOutput(String s) {
    outputTextArea.append(s);	
  }

  public void setOutput(String s) {
    outputTextArea.setText(s);	
  }

  // LISTENERS.
  private class KMTInputListener implements ActionListener {
    public void actionPerformed(ActionEvent evt) {
      String cmd = evt.getActionCommand();
      if (cmd.length() == 0) return;
      setInput( cmd);
      traceTextArea.setText("");
      eventHandler.new TranslateCommand(cmd).invokeLater();
    }
  }

  private class KMTModuleTraceListener implements ActionListener {
    private KantooConnection server;
    public KMTModuleTraceListener(KantooConnection server) {
      super();
      this.server = server;
    }
    public void actionPerformed(ActionEvent evt) {
      JCheckBox cb = (JCheckBox)evt.getSource();
      eventHandler.new ModuleCommand(server, cb.isSelected(),
				     evt.getActionCommand()).invokeLater();
    }
  }

  private class KMTRuleTraceListener implements ActionListener {
    private KantooConnection server;
    public KMTRuleTraceListener(KantooConnection server) {
      super();
      this.server = server;
    }
    public void actionPerformed(ActionEvent evt) {
      JRadioButton rb = (JRadioButton) evt.getSource();
      eventHandler.new RuleCommand( server, evt.getActionCommand()).invokeLater();
    }
  }

  private class KMTListListener implements ListSelectionListener {
    JList list;
    String cmd;
    public void valueChanged(ListSelectionEvent e) {
      if (e.getValueIsAdjusting()) return;
      list = (JList)e.getSource();
      if (list.isSelectionEmpty()) return;
      cmd = list.getSelectedValue().toString();
      if (cmd.length() == 0) return;
      setInput( cmd);
      traceTextArea.setText("");
      eventHandler.new TranslateCommand(cmd).invokeLater();
    }
  }

  // PANEL CONSTRUCTORS.
  private JPanel createOptionPanel() {
    // Create subpanels.
    JPanel activePanel = createActiveServerPanel();
    JPanel serverPanel = createConnectionPanel();
    JPanel anamodPanel = createModulePanel("analyzerModules","Analyzer Modules",anaModuleListener);
    JPanel genmodPanel = createModulePanel("generatorModules","Generator Modules",genModuleListener);
    JPanel anaknoPanel = createKnowledgePanel("analyzerKnowledgeBases","Analyzer Rules",anaRuleListener);
    JPanel genknoPanel = createKnowledgePanel("generatorKnowledgeBases","Generator Rules",genRuleListener);

    // Compose result.
    JPanel optionPanel = new JPanel(new GridBagLayout());
    // optionPanel.setBackground(Color.white);
    // optionPanel.setOpaque(true);
    GridBagConstraints gbc = new GridBagConstraints();
    // Insets: top, left, bottom, right
    gbc.fill = GridBagConstraints.BOTH;

    Insets    bottomLeftInsets = new Insets(4,8,8,2);
    Insets    bottomRightInsets= new Insets(4,2,8,8);
    Insets    headingInsets    = new Insets(4,4,4,4);
    Insets    leftInsets       = new Insets(4,8,0,2);
    Insets    rightInsets      = new Insets(4,2,0,8);

    gbc.anchor = GridBagConstraints.NORTH;
    gbc.gridx = 0; gbc.gridy = 0; gbc.gridwidth = 2; gbc.insets = headingInsets;
    JLabel serverOptions = new JLabel(" SERVER OPTIONS");
    serverOptions.setOpaque(true);
    serverOptions.setForeground(Color.black);
    optionPanel.add(serverOptions,gbc);
    gbc.gridx = 0; gbc.gridy = 1; gbc.gridwidth = 1; gbc.insets = bottomLeftInsets;
    optionPanel.add(activePanel,gbc);
    gbc.gridx = 1; gbc.gridy = 1; gbc.insets = bottomRightInsets;
    optionPanel.add(serverPanel,gbc);
    gbc.gridx = 0; gbc.gridy = 2; gbc.gridwidth = 2; gbc.insets = headingInsets;
    JLabel traceOptions = new JLabel(" TRACE OPTIONS");
    traceOptions.setOpaque(true);
    traceOptions.setForeground(Color.black);
    optionPanel.add(traceOptions,gbc);
    gbc.gridx = 0; gbc.gridy = 3; gbc.gridwidth = 1; gbc.insets = leftInsets;
    optionPanel.add(anamodPanel,gbc);
    gbc.gridx = 0; gbc.gridy = 4; gbc.insets = bottomLeftInsets;
    optionPanel.add(genmodPanel,gbc);
    gbc.gridx = 1; gbc.gridy = 3; gbc.insets = rightInsets;
    optionPanel.add(anaknoPanel,gbc);
    gbc.gridx = 1; gbc.gridy = 4; gbc.insets = bottomRightInsets;
    optionPanel.add(genknoPanel,gbc);

    return(optionPanel);
  }


  private JPanel createTracePanel(JTextArea textArea) {
    textArea.setFont(labelRegFont);
    textArea.setEditable(false);
    JScrollPane scrollPane = new JScrollPane(textArea);
    JPanel panel = new JPanel();
    panel.setLayout(new BorderLayout());
    panel.add(scrollPane);
    Dimension traceDimension = getDimensionProperty("trace");
    panel.setPreferredSize(traceDimension);
    panel.setMinimumSize(traceDimension);
    return(panel);
  }

  private JPanel createInputPanel() {

    JPanel panel = new JPanel();
    panel.setLayout(new BorderLayout());
    panel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Current"),emptyBorder));
    inputTextField = new JTextField();
    inputTextField.setFont(labelRegFont);
    inputTextField.addActionListener(inputListener);
    panel.add(inputTextField);

    JPanel panel2 = new JPanel();
    panel2.setLayout(new BorderLayout());
    panel2.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("History"),emptyBorder));

    InputStream inputStream =
      this.getClass().getResourceAsStream( properties.get("history.file"));
    Vector suiteItems = new Vector();
    loadSuite( suiteItems, inputStream);
    JList suiteList = new JList( suiteItems);
    suiteList.setFont(labelRegFont);
    suiteList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    suiteList.addListSelectionListener(listListener);
    suiteList.setVisibleRowCount(3);
    JScrollPane scrollPane = new JScrollPane(suiteList);
    panel2.add(scrollPane,BorderLayout.CENTER);
    Dimension historyDimension= getDimensionProperty("history");
    panel2.setPreferredSize(historyDimension);
    panel2.setMinimumSize(historyDimension);

    JPanel inputPanel = new JPanel();
    inputPanel.setLayout(new BorderLayout());
    inputPanel.add( "North", panel);
    inputPanel.add( "Center", panel2);
    return(inputPanel);
  }

  private JPanel createActiveServerPanel() {
    JPanel serverPanel = new JPanel();
    serverPanel.setBackground(Color.white);
    serverPanel.setOpaque(true);
    serverPanel.setLayout(new GridBagLayout());
    GridBagConstraints gbc1 = new GridBagConstraints();
    gbc1.anchor = GridBagConstraints.WEST;
    serverPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Active Servers"),emptyBorder));
    gbc1.gridx=0;
    gbc1.gridy=0;
    JCheckBox analyzerOption = new JCheckBox("Analyzer");
    analyzerOption.setOpaque(false);
    // analyzer is always turned on.
    analyzerOption.setSelected(true);
    analyzerOption.setEnabled(false);
    serverPanel.add(analyzerOption,gbc1);
    gbc1.gridy=1;
    JCheckBox generatorOption = new JCheckBox("Generator");
    generatorOption.setOpaque(false);
    generatorOption.setSelected(true);
    generatorOption.addItemListener(new ItemListener() {
	public void itemStateChanged(ItemEvent e) {
	  eventHandler.generatorActive = (e.getStateChange() == ItemEvent.SELECTED);
	}
      });
    serverPanel.add(generatorOption,gbc1);
    return(serverPanel);
  }

  private JPanel createKnowledgePanel(String propertyName, String panelName, ActionListener ruleListener) {
    JPanel kpanel = new JPanel();
    kpanel.setBackground(Color.white);
    kpanel.setOpaque(true);
    kpanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(panelName),emptyBorder));
    kpanel.setLayout(new GridBagLayout());
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.gridx = 0;
    gbc.gridy = 0;
    gbc.insets = new Insets(0,4,0,4);
    String headings[] = {"None","Fired","Tried"};             // used in the GUI
    String cmdHeadings[] = {"None","Succeeded","Applicable"}; // recognized by KANTOO
    gbc.anchor = GridBagConstraints.CENTER;
    for (int i = 0; i < headings.length; i++) {
      gbc.gridx = gbc.gridx + 1;
      kpanel.add(new JLabel(headings[i]),gbc);
    }
    String labelString;
    StringTokenizer knowledgeReader = new StringTokenizer(properties.get(propertyName),",");
    gbc.gridy = 1;
    while (knowledgeReader.hasMoreTokens()) {
      labelString = knowledgeReader.nextToken();
      gbc.gridx = 0;
      gbc.anchor = GridBagConstraints.WEST;
      JLabel jl = new JLabel(labelString);
      jl.setForeground(Color.black);
      kpanel.add(jl,gbc);
      ButtonGroup buttons = new ButtonGroup();
      for (int i = 0; i < 3; i++) {
	gbc.anchor = GridBagConstraints.CENTER;
	gbc.gridx = gbc.gridx + 1;
	JRadioButton button = new JRadioButton();
	button.setActionCommand(cmdHeadings[i]+" "+labelString);
	button.addActionListener(ruleListener);
	button.setBackground(Color.white);
	button.setOpaque(true);
	kpanel.add(button,gbc);
	if (i == 0) button.setSelected(true);
	buttons.add(button);
      }
      gbc.gridy = gbc.gridy + 1;
    }
    gbc.gridx=0; gbc.weighty = 2.0; kpanel.add(new JLabel(),gbc);
    return(kpanel);
  }

  private JPanel createModulePanel(String propertyName, String panelName, ActionListener moduleListener) {
    JPanel panel2 = new JPanel();
    panel2.setBackground(Color.white);
    panel2.setOpaque(true);
    panel2.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(panelName),emptyBorder));
    panel2.setLayout(new GridBagLayout());
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.gridx = 0;
    gbc.gridy = 0;
    gbc.anchor = GridBagConstraints.WEST;
    StringTokenizer moduleReader = new StringTokenizer(properties.get(propertyName),",");
    while (moduleReader.hasMoreTokens()) {
      String moduleName = moduleReader.nextToken();
      JCheckBox checkBox = new JCheckBox(moduleName);
      checkBox.setActionCommand(moduleName);
      checkBox.addActionListener(moduleListener);
      checkBox.setBackground(Color.white);
      checkBox.setOpaque(true);
      panel2.add(checkBox,gbc);
      gbc.gridy = gbc.gridy + 1;
    }
    return(panel2);
  }


  private JPanel createConnectionPanel() {
    JPanel cxnPanel = new JPanel();
    cxnPanel.setBackground(Color.white);
    cxnPanel.setOpaque(true);
    cxnPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Server Connections"),emptyBorder));
    GridBagConstraints gc = new GridBagConstraints();
    gc.insets = new Insets(0,4,0,4);
    cxnPanel.setLayout(new GridBagLayout());
    int rows, cols;
    gc.gridx = 1;
    gc.gridy = 0;
    gc.anchor = GridBagConstraints.WEST;
    gc.gridx=2;
    gc.gridy=0;
    analyzerLabel = new JLabel();
    analyzerLabel.setOpaque(false);

    eventHandler.getAnalyzer().setListener(new Connection.Listener() {
	public void connectionChanged(boolean connected) {
	  analyzerLabel.setText( connected ? eventHandler.getAnalyzer().getConfig().toString() : "Disconnected");
	}});
    cxnPanel.add(analyzerLabel,gc);
    gc.gridy=1;
    generatorLabel = new JLabel();
    generatorLabel.setOpaque(false);
    eventHandler.getGenerator().setListener(new Connection.Listener() {
	public void connectionChanged(boolean connected) {
	  generatorLabel.setText( connected ? eventHandler.getGenerator().getConfig().toString() : "Disconnected");
	}});
    cxnPanel.add(generatorLabel,gc);
    gc.gridy=2;
    versionerLabel = new JLabel();
    versionerLabel.setOpaque(false);
    versionerLabel.setText( properties.get("versionerServer") + ":" + properties.get("versionerPort"));
    cxnPanel.add(versionerLabel,gc);
    gc.gridx=0;
    gc.gridy=0;
    gc.anchor = GridBagConstraints.CENTER;
    analyzerStatus = new JLabel("?");
    analyzerStatus.setOpaque(false);
    cxnPanel.add(analyzerStatus,gc);
    gc.gridy=1;
    generatorStatus = new JLabel("?");
    generatorStatus.setOpaque(false);
    cxnPanel.add(generatorStatus,gc);
    gc.gridy=2;
    versionerStatus = new JLabel("?");
    versionerStatus.setOpaque(false);
    cxnPanel.add(versionerStatus,gc);
    return cxnPanel;
  }

  private JPanel createSuitePanel( String filename) {
    Vector suiteVector = new Vector();
    try {
      if (filename == null || filename.length() == 0)
	filename = properties.get("suite.url");
      InputStream inputStream;
      try {
	URL url = new URL( filename);
	inputStream = url.openStream();
      } catch (MalformedURLException e) {
	inputStream = new FileInputStream( filename);
      }
      loadSuite( suiteVector, inputStream);
    } catch (IOException e) {ReportError.warning(e);}
    suiteList = new JList(suiteVector);
    suiteList.setFont(labelRegFont);
    suiteList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    suiteList.addListSelectionListener(listListener);
    JScrollPane suiteScroll = new JScrollPane(suiteList);

    JPanel suitePanel = new JPanel();
    suitePanel.setLayout(new BorderLayout());
    suitePanel.add(suiteScroll);

    Dimension suiteDimension = getDimensionProperty("suite");
    suitePanel.setPreferredSize(suiteDimension);
    suitePanel.setMinimumSize(suiteDimension);
    return suitePanel;
  }

  // METHODS
  private void loadSuite(Vector v, InputStream inputStream) {
    String inputString, status, content;
    v.removeAllElements();
    try {
      Reader suiteFileReader = new InputStreamReader( inputStream);
      BufferedReader in = new BufferedReader(suiteFileReader);
      while (true) {
	inputString = in.readLine();
	if (inputString == null) { break; }
	status = null;
	content = inputString;
	v.addElement(content);
      }
      in.close();
      suiteFileReader.close();
    } catch (Exception e) {ReportError.bug(e);}
  }

  public JInternalFrame addFrame(String name, JComponent c, boolean resizeable) {
    JInternalFrame f = new JInternalFrame(name,resizeable,false,resizeable,true);
    desk.add(f,1);
    JComponent pane = (JComponent) f.getContentPane();
    pane.add(c);
    f.setLocation( Integer.parseInt( properties.get(name+".x")),
		   Integer.parseInt( properties.get(name+".y")));
    f.pack();
    f.show();
    f.addVetoableChangeListener(iconPolice);
    internalFrames.addElement(f);
    return f;
  }

  public void showPositions() {
    for (int i = 0; i < internalFrames.size(); i++) {
      JInternalFrame f = (JInternalFrame)internalFrames.elementAt(i);
      Point p = f.getLocation();
      logger.fine( f.getTitle()+": "+p.getX()+","+p.getY());
    }
  }

  public void fatalError(String s) {
    JOptionPane.showMessageDialog(null, s, "Fatal Error", JOptionPane.ERROR_MESSAGE);	
    System.exit(-1);
  }

  // INNER CLASSES
  class IconPolice implements VetoableChangeListener {
    public void vetoableChange(PropertyChangeEvent ev) throws PropertyVetoException {
      String name = ev.getPropertyName();
      if (name.equals(JInternalFrame.IS_ICON_PROPERTY) && (ev.getNewValue() == Boolean.TRUE)) {
	JInternalFrame[] frames = desk.getAllFrames();
	int count = frames.length;
	int nonicons = 0;
	for (int i=0; i<count; i++) {
	  if (frames[i].isIcon() == false) nonicons++;
	}
	if (nonicons <= 1) throw new PropertyVetoException("Invalid Iconification!", ev);
      }
    }
  }


  /**
   * Main procedure
   */
  public static void main(String[] args) {
    String filename = PropertyManager.getArgs( args);

    final KMTDesktop td = new KMTDesktop("KMT Desktop", filename);
    new PropertyActor( td.properties, "desktop").loadDimensions( td);
    td.addWindowListener(new WindowAdapter() {
	public void windowClosing(WindowEvent w) {
	  td.properties.store();
	  System.exit(0);
	}
      });

    try {
      HelpSet hs = new HelpSet(null, td.getProperties().getResource( td.getProperties().get("kmt.url")));
      helpBroker = hs.createHelpBroker();
    } catch (Exception ee) {ReportError.warning(ee);}
    KMTHelpActionListener = new javax.help.CSH.DisplayHelpFromSource( helpBroker);
    KCEhelpActionListener = new javax.help.CSH.DisplayHelpFromSource( Issue.getHelpBroker());
    td.setVisible(true);
  }


  public static final String exitAction = "exit";

  /**
   * the set of commands we support
   */
  private ActionMap commands;

  /**
   * Actions defined by the Notepad class
   */
  private Action[] defaultActions = {
    new ExitAction(),
    new ServersAction(),
    new SuiteAction(),
    new KCEHelpAction(),
    new KMTHelpAction(),
  };

  /**
   * Really lame implementation of an exit command
   */
  class ExitAction extends AbstractAction {

    ExitAction() {super(exitAction);}

    public void actionPerformed(ActionEvent e) {
      properties.store();
      System.exit(0);
    }
  }

  /**
   * Class for changing the analyzer & generator servers being utilized
   */
  class ServersAction extends AbstractAction {
    /**
     * Constructor to name the action
     */
    ServersAction() {super("servers");}

    public void actionPerformed(ActionEvent e) {
      ConnectionConfig.showDialog( new Connection[] {
	eventHandler.getAnalyzer(), eventHandler.getGenerator()});
    }
  }

  /**
   * Class for changing the test suite being used
   */
  class SuiteAction extends AbstractAction {
    /**
     * Constructor to name the action
     */
    SuiteAction() {super("suite");}

    public void actionPerformed(ActionEvent e) {
      JFileChooser fc = new JFileChooser( System.getProperty("user.dir"));
      if (fc.showOpenDialog( null) != JFileChooser.APPROVE_OPTION) return;
      try {
	Vector suiteItems = new Vector();
	InputStream inputStream = new FileInputStream( fc.getSelectedFile());
	loadSuite( suiteItems, inputStream);
	suiteList.setListData( suiteItems);
      } catch (FileNotFoundException x) {ReportError.warning(x);}
    }
  }


  static private ActionListener KCEhelpActionListener = null;

  class KCEHelpAction extends AbstractAction {
    public KCEHelpAction() {super("kce");}

    public void actionPerformed(ActionEvent e) {
      KCEhelpActionListener.actionPerformed(e);
    }
  }

  /**
   * A help broker for displaying help about the CLChecker
   */
  static private HelpBroker helpBroker = null;
  static private ActionListener KMTHelpActionListener = null;

  class KMTHelpAction extends AbstractAction {
    public KMTHelpAction() {super("kmt");}

    public void actionPerformed(ActionEvent e) {
      KMTHelpActionListener.actionPerformed(e);
    }
  }
}
