Package fbench

Source Code of fbench.FBench$StreamLogger

// Copyright (c)2005 Holobloc Inc.
// Contributed to the OOONEIDA FBench project under the Common Public License.

// Copyright (c) 2007 University of Auckland
// Contributed to the FBench extension of the OOONEIDA Workbench project under the Common Public License

package fbench;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Hashtable;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.Vector;

import javax.swing.AbstractAction;
import javax.swing.AbstractButton;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JToolBar;
import javax.swing.JTree;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.WindowConstants;

import javax.swing.event.MenuEvent;
import javax.swing.event.MenuListener;
import javax.swing.tree.TreeSelectionModel;

import fbench.dom.DOMTranslationModel;
import fbench.dom.DocumentSource;
import fbench.graph.GraphViewTransfer;
import fbench.plugin.PluginManager;
import fbench.translate.JavaToJava;
import fbench.translate.JavaToSRC;
import fbench.translate.STtoJava;
import fbench.translate.STtoSRC;
import fbench.translate.TranslatorSource;
import fbench.tree.LibraryTreeNode;
import fbench.ui.TabPanel;

import org.w3c.dom.Document;

import fb.rt.FBInstance;

// import fb.rt.tools.SystemLogger;
// import fb.rt.tools.SystemManager;
// import fb.tools.FBELibrarySpec;
// import fb.tools.FileLibrary;
// import fb.tools.swing.editor.FBJPreferences;

/**
* A desktop for multiple Editors.
*
* @author WD,AS,JHC,JP
*
* @version 20070422/JP - Separated plug-in features from the kernel parts
* @version 20061127/WD - Remove Left Tree,Add open function to the menu
* @version 20060914/WD - Added System Configurations Debugging
* @version 20051129/JHC - Eliminated use of DTDs; ElementTableModel now sets up own attribute names.
* @version 20051128/JHC - Set up main pane as JSplitPane with library view as left element.
* @version 20050810/JHC - First OOONEIDA version.
* @version 20050803/JHC - Changed desktop to JTabbedPane.
* @version 20050709/JHC
*/
public class FBench extends JFrame implements DocumentSource, ActionListener, MenuListener {

  private static final long serialVersionUID = -2684239640734884416L;

  public static final String productID = "IEC 61499 FBench";

  public static final String version = "v1.0 Build 20070820";

  public static Hashtable<String, Process> processes = new Hashtable<String, Process>();

  public static FBench theBench = null;

    private static String rtPathRoot = "";

  public static String getRTPathRoot() {
    return rtPathRoot;
  }
   
  private Hashtable<String, Object> instances = new Hashtable<String, Object>();

  /** The TransferHandler for dragging components into GraphViews. */
  private GraphViewTransfer gvhandler;

  private Properties preferences = new Properties();

  // private Properties debugPreferences = new Properties();

  private JTabbedPane desktop = new JTabbedPane();
  // private CloseTabbedPane desktop = new CloseTabbedPane();

  private JToolBar toolBar = new JToolBar(1);

  /** For View Menu */
  private JFrame viewFrame = new JFrame("FBench Library");

  private JPopupMenu refresh_view = new JPopupMenu();

  private JMenuItem refresh_viewwini =
      createMenuItem("Refresh", "reloadLibraryTree", "Refresh16", "Refresh", 'R', null);

  private JMenuBar mb = new JMenuBar();

  private JMenu fileMenu = new JMenu("File");

  private JMenu fileNewMenu = new JMenu("New");

  private JMenu fileNewFBMenu = new JMenu("FB Type");

  private JMenu fileNewDataMenu = new JMenu("Data Type");

  private JMenuItem newBFB =
      createMenuItem("Basic FB", "fbench.FBench.newBFB", "New16", "Create a basic function block", 'B',
              null);

  private JMenuItem newCFB =
      createMenuItem("Composite FB", "fbench.FBench.newCFB", "New16", "Create a composite block", 'C',
              null);

  private JMenuItem newProxy =
      createMenuItem("Proxy FB", "fbench.FBench.newProxy", "New16", "Create a proxy", 'P', null);

  private JMenuItem newSI =
      createMenuItem("Service Interface FB", "fbench.FBench.newSI", "New16",
              "Create a service interface function block", 'S', null);

  private JMenuItem newSimple =
      createMenuItem("Simple FB", "fbench.FBench.newSimple", "New16", "Create a simple function block",
              'I', null);

  private JMenuItem newAdapt =
      createMenuItem("Adapter Type", "fbench.FBench.newAdapt", "New16", "Create an adapter", 'A', null);

  private JMenuItem newRes =
      createMenuItem("Resource Type", "fbench.FBench.newRes", "New16", "Create a resource", 'N', null);

  private JMenuItem newDev =
      createMenuItem("Device Type", "fbench.FBench.newDev", "New16", "Create a device", 'D', null);

  private JMenuItem newSys =
      createMenuItem("System", "fbench.FBench.newSys", "New16", "Create a system configuration", 'Y',
              null);

  private JMenuItem fileOpen =
      createMenuItem("Open...", "fbench.FBench.FileOpen", "Open16", "Open an existing file", 'O',
              InputEvent.CTRL_MASK);

  private JMenu fileSaveAsMenu = new JMenu("Save As");

  private JMenuItem fileSaveAsXMLItem =
      createMenuItem("XML...", "fbench.FBench.fileSaveAsXML", "xmlObject",
              "Save current document as XML file", 'S', InputEvent.CTRL_MASK);

  // private JMenuItem ProjectEnv =
  // createMenuItem("New16", "Project Environment",
  // "fbench.FBench.projectenv");

  private JMenuItem fileExitItem =
      createMenuItem("Exit", "fbench.FBench.fileExit", "Close", "Exit FBench", null);

  private JMenu editMenu = new JMenu("Edit");

  private JMenuItem editUndoItem =
      createMenuItem("Undo", "fbench.FBench.editAction", "Undo16", "Undo last action", 'Z',
              InputEvent.CTRL_MASK);

  private JMenuItem editRedoItem =
      createMenuItem("Redo", "fbench.FBench.editAction", "Redo16", "Redo last action", 'Y',
              InputEvent.CTRL_MASK);

  private JMenuItem editCutItem =
      createMenuItem("Cut", "fbench.FBench.editAction", "Cut16", "Move selected text to clipboard",
              null);

  private JMenuItem editCopyItem =
      createMenuItem("Copy", "fbench.FBench.editAction", "Copy16", "Copy text to clipboard", null, null);

  private JMenuItem editPasteItem =
      createMenuItem("Paste", "fbench.FBench.editAction", "Paste16",
              "Replace selected text with clipboard contents", null);

  private JMenuItem editDeleteItem =
      createMenuItem("Delete", "fbench.FBench.editAction", "Delete16",
              "Permanently delete selected text", null);

  private JMenuItem editFindReplaceItem =
      createMenuItem("Find/Replace...", "fbench.FBench.editAction", "Find16",
              "Open Find/Replace Dialog", null);

  private JMenuItem editSelectAllItem =
      createMenuItem("Select All", "fbench.FBench.editAction", null, "Select all text", 'A',
              InputEvent.CTRL_MASK);

  private JMenu viewMenu = new JMenu("View");

  private JCheckBoxMenuItem treeViewMenu =
      new JCheckBoxMenuItem("Display Library Tree Window", IconFactory.getIcon("Open16"));

  private JMenu compileMenu = new JMenu("Compile");

  private JMenuItem compiletoJava =
      createMenuItem("Compile to Java", "fbench.FBench.fileSaveAsJava", "compile16", "Compile to Java",
              KeyStroke.getKeyStroke(KeyEvent.VK_F5, 0));

  private JMenuItem compiletoJavaDebug =
      createMenuItem("Compile to Java with Debug", "fbench.FBench.fileSaveAsJavaDebug", "compile16",
              "Compile to Java with remote debugging(FBRT)", KeyStroke
                  .getKeyStroke(KeyEvent.VK_F6, 0));

  private JMenu runMenu = new JMenu("Run");

  private JMenu runLaunchMenu = new JMenu("Launch");

  private JMenuItem runLaunchItem =
      createMenuItem("Launch", "fbench.FBench.runLaunch", "fb",
              "Launches a system configuration or an instance of an FB type.", KeyStroke
                  .getKeyStroke(KeyEvent.VK_F7, 0));

  private JMenu helpMenu = new JMenu("Help");

  private JMenuItem helpItem =
      createMenuItem("User Manual", "fbench.FBench.help", "Help16", "FBench Help", KeyStroke
          .getKeyStroke(KeyEvent.VK_F1, 0));

  private JMenuItem helpHowToItem =
      createMenuItem("Developer's Guide", "fbench.FBench.help", "Help16", "FBench tutorial", null);

  private JMenuItem helpAboutItem =
      createMenuItem("About FBench", "fbench.FBench.help", "Help16", "Contact Information", null);

  // gsha041: Speed fix for JFileChooser... (known problem / issue @ sun)
  // it takes AAAAAAAAAGES to create this... so init 1ce use many times :D
  // using java.awt.FileChooser...
  private final JFileChooser select_item = new JFileChooser("src");

  // gsha041: Hashtable of Avaliable ElementModels...(string "name", string
  // className)
  /** Avaliable GraphModel Classes for Visualisation */
  private static Hashtable<String, String> graphModels = new Hashtable<String, String>(32);

  /** Avaliable GraphElement Classes for Visualisation */
  private static Hashtable<String, String> graphElements = new Hashtable<String, String>(32);

  /** Avaliable mutationListener Classes for 'listening' */
  private static Hashtable<String, String> mutationListeners = new Hashtable<String, String>(32);

  /** Avaliable treeNode Classes for Visualisation in DOMTree */
  private static Hashtable<String, String> treeNodes = new Hashtable<String, String>(32);

  /**
   * Avaliable treeMenu Classes for ContextMenus in DOMTree String = Element Type String[] = Strings of
   * Context Menu Options
   */
  private static Hashtable<String, String[]> treeMenus = new Hashtable<String, String[]>(32);

  /**
   * Avaliable (tree)MenuAction Dialogs / Classes String = Element Type String = Class name of Action /
   * Dialog
   */

  private static Hashtable<String, String> treeMenuActions = new Hashtable<String, String>(32);

  private PluginManager plugin;

  private JPanel statusJPanel = new JPanel();
  private JLabel statusJLabel = new JLabel("Ready");;

  public void setStatusText(String message) {
    this.statusJLabel.setText(message);
  }

  public FBench() {
    super();
    theBench = this;
    Library.setDocumentSource(this);
    setupPreferences();
    setTitle(FBench.productID);
    setIconImage(IconFactory.getIcon("fbench0.jpg").getImage());
    setLayout(new BorderLayout());
    desktop.setFont(new Font("SansSerif", Font.PLAIN, 10));
    desktop.addMouseListener(new MouseAdapter() {
      public void mouseClicked(MouseEvent e) {
        checkToolBar();
      }
    });

    instances.put("fbench.FBench", this);

    final FBench me = this;
    setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        me.windowClosing(evt);
      }
    });

    menuBarInit();

    toolBar.setBorder(BorderFactory.createEtchedBorder());
    toolBar.setFloatable(true);

    String[] newFunctions = {"Parse XML", "Save Now", "Close Tab", "Previous Tab", "Next Tab"};
    String[] newPics =
        {"fbench/images/Refresh16.gif", "fbench/images/SaveAs16.gif", "fbench/images/Close16.gif",
          "fbench/images/arrow15l.gif", "fbench/images/arrow15r.gif"};
    buildToolButton(toolBar, newFunctions, newPics);
    getContentPane().add(toolBar, BorderLayout.WEST);

    getContentPane().add(desktop, BorderLayout.CENTER);

    statusJLabel.setFont(new Font("SansSerif", Font.PLAIN, 12));
    statusJPanel.setLayout(new BorderLayout(10, 3));
    statusJPanel.add(statusJLabel);
    getContentPane().add(statusJPanel, BorderLayout.SOUTH);

    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    int screenWidth = screenSize.width;
    int screenHeight = screenSize.height;

    setBounds(screenWidth / 8, screenHeight / 8, 3 * screenWidth / 4, 3 * screenHeight / 4);

    Vector<String> helpArg = new Vector<String>();
    helpArg.add(new String("About"));
    if(help(helpArg) != JOptionPane.OK_OPTION)
      System.exit(-1);
    setVisible(true);

    TranslatorSource.getInstance().addTranslator(STtoJava.class, "ST", "Java");
    TranslatorSource.getInstance().addTranslator(STtoSRC.class, "ST", "SRC");
    TranslatorSource.getInstance().addTranslator(JavaToJava.class, "Java", "Java");
    TranslatorSource.getInstance().addTranslator(JavaToSRC.class, "Java", "SRC");

    String openfiles = preferences.getProperty("openfiles");
    if(openfiles != null) {
      StringTokenizer toker = new StringTokenizer(openfiles, ",");
      while(toker.hasMoreElements())
        open(toker.nextToken());
    }
  }

  /**
   * Use reflection to refresh the items under plug-in menus
   *
   * @param evt MenuEvent
   */
  public void menuSelected(MenuEvent evt) {
    Object src = evt.getSource();
    if(src == editMenu)
      editMenuSelected();
    else if(src == runMenu)
      runMenuSelected();
    else if(src == compileMenu)
      CompileSelected();
    else {
      String actionCommand = ((JMenu) evt.getSource()).getActionCommand();
      String callerName = actionCommand.substring(0, actionCommand.lastIndexOf("."));
      String methodName = actionCommand.substring(actionCommand.lastIndexOf(".") + 1);

      Vector<Object> args = new Vector<Object>();
      args.add((JMenu) evt.getSource());
      args.add(this);

      try {
        Class<?> caller = Class.forName(callerName);

        Method method = caller.getMethod(methodName, Vector.class);

        java.util.Hashtable<String, Object> instances = getInstances();

        Object instance = instances.get(callerName);
        if(instance == null) {
          instance = caller.newInstance();
          instances.put(callerName, instance);
        }

        method.invoke(instance, args);

      }
      catch(ClassNotFoundException e) {
        e.printStackTrace();
      }
      catch(SecurityException e) {
        e.printStackTrace();
      }
      catch(NoSuchMethodException e) {
        e.printStackTrace();
      }
      catch(InstantiationException e) {
        e.printStackTrace();
      }
      catch(IllegalAccessException e) {
        e.printStackTrace();
      }
      catch(InvocationTargetException e) {
        e.printStackTrace();
      }
    }
  }

  /**
   * Use reflection to invoke the action associated with the selected menu item
   *
   * @param evt ActionEvent
   */
  public void actionPerformed(ActionEvent evt) {
    String cmd = ((AbstractButton) evt.getSource()).getText();
    String actionCommand = evt.getActionCommand();
    String callerName = actionCommand.substring(0, actionCommand.lastIndexOf("."));
    String methodName = actionCommand.substring(actionCommand.lastIndexOf(".") + 1);

    Class<?>[] parameterTypes = new Class[1];
    parameterTypes[0] = Vector.class;

    Vector<Object> args = new Vector<Object>();
    args.add(cmd);
    args.add(this);
    String cmdtxt = methodName + "(\"" + cmd + "\")\n";
    try {
      Class<?> caller = Class.forName(callerName);
      Method method = caller.getMethod(methodName, parameterTypes);

      Object instance = instances.get(callerName);
      if(instance == null) {
        instance = caller.newInstance();
        instances.put(callerName, instance);
      }

      method.invoke(instance, args);
    }
    catch(IllegalArgumentException e) {
      e.printStackTrace();
      System.err.println(cmdtxt + e);
    }
    catch(SecurityException e) {
      e.printStackTrace();
      System.err.println(cmdtxt + e);
    }
    catch(IllegalAccessException e) {
      e.printStackTrace();
      System.err.println(cmdtxt + e);
    }
    catch(InvocationTargetException e) {
      e.printStackTrace();
      System.err.println(cmdtxt + e);
      System.err.println("Cause: " + e.getCause());
    }
    catch(NoSuchMethodException e) {
      e.printStackTrace();
      System.err.println(cmdtxt + e);
    }
    catch(Exception e) {
      System.err.print(e);
    }
  }

  /**
   *
   */
  private void menuBarInit() {
    plugin = new PluginManager(this);

    mb.add(fileMenu);
    fileMenu.add(fileNewMenu);
    fileNewMenu.add(fileNewFBMenu);
    fileNewFBMenu.add(newBFB);
    fileNewFBMenu.add(newCFB);
    fileNewFBMenu.add(newProxy);
    fileNewFBMenu.add(newSI);
    fileNewFBMenu.add(newSimple);
    fileNewMenu.add(fileNewDataMenu);
    fileNewMenu.add(newAdapt);
    fileNewMenu.add(newRes);
    fileNewMenu.add(newDev);
    fileNewMenu.add(newSys);
    fileNewMenu.setIcon(IconFactory.getIcon("New16"));
    fileMenu.add(fileOpen);
    fileMenu.addSeparator();
    fileMenu.add(fileSaveAsMenu);
    fileSaveAsMenu.add(this.fileSaveAsXMLItem);
    fileSaveAsMenu.setIcon(IconFactory.getIcon("SaveAs16"));
    // fileMenu.addSeparator();
    // fileMenu.add(ProjectEnv);
    fileMenu.addSeparator();
    fileMenu.add(fileExitItem);

    mb.add(editMenu);
    editMenu.addMenuListener(this);
    editMenu.add(editUndoItem);
    editMenu.add(editRedoItem);
    editMenu.addSeparator();

    editCutItem.setAccelerator(KeyStroke.getKeyStroke("control X"));
    editMenu.add(editCutItem);
    editCopyItem.setAccelerator(KeyStroke.getKeyStroke("control C"));
    editMenu.add(editCopyItem);
    editPasteItem.setAccelerator(KeyStroke.getKeyStroke("control V"));
    editMenu.add(editPasteItem);
    editDeleteItem.setAccelerator(KeyStroke.getKeyStroke("DELETE"));
    editMenu.add(editDeleteItem);
    editMenu.addSeparator();
    editFindReplaceItem.setAccelerator(KeyStroke.getKeyStroke("control F"));
    editMenu.add(editFindReplaceItem);
    editMenu.addSeparator();
    editMenu.add(editSelectAllItem);

    mb.add(viewMenu);
    viewMenu.add(treeViewMenu);
    treeViewMenu.addActionListener(this);
    treeViewMenu.setActionCommand("fbench.FBench.runViewMenu");

    refresh_viewwini.setIcon(new ImageIcon("fbench/images/Refresh16.gif"));
    refresh_view.add(refresh_viewwini);

    mb.add(compileMenu);
    compileMenu.add(compiletoJava);
    compileMenu.add(compiletoJavaDebug);
    compileMenu.addMenuListener(this);

    mb.add(runMenu);
    runLaunchMenu.setIcon(IconFactory.getIcon("Play16"));
    runLaunchMenu.add(runLaunchItem);
    runMenu.add(runLaunchMenu);
    runMenu.addMenuListener(this);

    // Resourced from:
    // http://jug.org.ua/wiki/display/JavaAlmanac/Getting+the+Currently+Selected+Menu+or+Menu+Item

    /*
     * TODO: A JMenu can contain four kinds of items: JMenu, JMenuItem, JCheckBoxMenuItem, and
     * JRadioButtonMenuItem. However, JMenuItem is the direct super class of the other three items. In the
     * PluginSchema.xsd, JMenu maps Menu, JMenuItem maps MenuItem, JCheckBoxMenuItem maps CheckBox, and
     * JRadioButtonMenuItem maps RadioButton. Therefore, for each of them we need to parse them
     * differently and perhaps merge them accordingly. For the time being, only JMenuItem and JMenu are
     * supported.
     */
    for(JMenu jMenu : this.plugin.loadMenuItems()) {
      // System.out.println("[FB] item menu name: " + item.getText());
      JMenu parentMenu = getExistJMenu(jMenu);

      if(parentMenu == null) {
        // System.out.println("JMenu: {" + item.getText() + "} does not
        // exist.");
        mb.add(jMenu);
      }
      else {
        // System.out.println("JMenu: {" + item.getText() + "} already
        // exists.");
        mergeMenuWithParent(jMenu, parentMenu);
      }
    }

    mb.add(helpMenu);
    // If the preferred browse is not set, use the system default one
    // boolean canbrowse = (preferences.getProperty("browser") != null);
    boolean canbrowse = true;
    helpMenu.add(helpItem);
    helpItem.setEnabled(canbrowse);
    helpMenu.add(helpHowToItem);
    helpHowToItem.setEnabled(canbrowse);
    helpMenu.addSeparator();
    helpMenu.add(helpAboutItem);

    setJMenuBar(mb);
  }

  /**
   * Check whether the given JMenu instance has already been added to the menu bar. If the target JMenu has
   * not been added, return it otherwise return null
   *
   * @param target JMenu
   * @return JMenu or <TT>null</TT>
   */
  private JMenu getExistJMenu(JMenu target) {
    for(int i = 0; i < mb.getMenuCount(); i++) {
      JMenu jMenu = mb.getMenu(i);
      String label = jMenu.getText();
      if(label.equalsIgnoreCase(target.getText())) {
        return jMenu;
      }
    }
    return null;
  }

  /**
   * Check whether the given JMenuItem resides in the given JMenu. Only return the item in sourceJMenu if it
   * has the same name as that of targetItem
   *
   * @param targetItem JMenuItem, can be JMenuItem, JCheckBoxMenuItem, or JRadioButtonMenuItem
   * @param sourceJMenu JMenu
   * @return JMenuItem or <TT>null</TT>
   */
  private JMenuItem getExistJMenuItem(JMenuItem targetItem, JMenu sourceJMenu) {
    // System.out.println("Locating " + targetItem.getText() + " within " + sourceJMenu.getText());

    String targetItemLabel = targetItem.getText();

    for(int i = 0; i < sourceJMenu.getItemCount(); i++) {
      JMenuItem item = sourceJMenu.getItem(i);
      if(targetItemLabel.equalsIgnoreCase(item.getText())) {
        return item;
      }
    }
    return null;
  }

  /**
   * Recursively merge the target menu to the parent menu. Only the first non-exist menu item will be added
   *
   * @param item JMenuItem
   * @param parentMenu JMenu
   */
  private void mergeMenuWithParent(JMenuItem item, JMenu parentMenu) {
    JMenuItem newParent = null;
    // TODO: When merging newJMenu with oldJMenu, we actually check the items within the JMenu's, however
    // we didn't change anything about the oldJMenu itself. That's why the ActionCommand, typically the
    // refreshMenu method, associated with the newJMenu is never added to the oldJMenu.
    if(item instanceof JMenu) {
      // System.out.println(" [Megering] JMenu name: " + item.getText());
      // System.out.println(" old action command: " + parentMenu.getActionCommand());
      // System.out.println(" new action command: " + item.getActionCommand());
      // parentMenu.setActionCommand(item.getActionCommand());
      // System.out.println(" new added action command: " + parentMenu.getActionCommand());
      JMenu jMenu = (JMenu) item;
      for(int i = 0; i < jMenu.getItemCount(); i++) {
        JMenuItem subMenuItem = jMenu.getItem(i);
        newParent = getExistJMenuItem(subMenuItem, parentMenu);
        if(newParent == null) {
          parentMenu.add(subMenuItem);

          // must decrement the i counter as the subMenuItem has been removed from jMenu, which also
          // decrement the value of jMenu.getItemCount()
          i--;
        }
        else {
          // if the newParent item exists and its not a JMenu, then don't add it, otherwise merge
          // the newParent with subMenuItem again
          if(newParent instanceof JMenu) {
            mergeMenuWithParent(subMenuItem, (JMenu) newParent);
          }
        }
      }
    }
    else { // All other kinds of menu items: JMenuItem, JCheckBoxMenuItem, etc
      newParent = getExistJMenuItem(item, parentMenu);
      if(newParent == null) {
        parentMenu.add(item);
      }
    }
  }

  private void buildToolButton(JToolBar toolBar, String[] functions, String[] pics) {
    JButton button;

    for(int i = 0; i < functions.length; i++) {
      ActionSet action = new ActionSet(functions[i], new ImageIcon(pics[i]));
      button = toolBar.add(action);
      button.setActionCommand(functions[i]);
      button.setToolTipText((String) action.getValue(Action.NAME));
      button.setEnabled(false);
    }
  }

  private void checkToolBar() {
    int count = desktop.getTabCount();
    int selected = desktop.getSelectedIndex();
    boolean enabled = count > 0;
    toolBar.getComponent(0).setEnabled(enabled);
    toolBar.getComponent(1).setEnabled(enabled);
    toolBar.getComponent(2).setEnabled(enabled);
    toolBar.getComponent(3).setEnabled(enabled && selected > 0);
    toolBar.getComponent(4).setEnabled(enabled && selected < count - 1);
  }

  protected void windowClosing(WindowEvent evt) {
    // Check if All Files have been saved
    if(unsavedFiles())
      return;
    for(Process proc : processes.values())
      proc.destroy();
    dispose();
    System.exit(0);
  }

  private boolean unsavedFiles() {
    for(int i = 0; i < desktop.getComponentCount(); i++) {
      Component c = desktop.getComponent(i);
      if(c instanceof LibraryElementView) {
        LibraryElementView doc = ((LibraryElementView) c);
        if(!doc.safeToClose()) {
          return true;
        }
      }
    }
    return false;
  }

  public void closeTab(Component c) {
    if(c instanceof LibraryElementView) {
      LibraryElementView doc = ((LibraryElementView) c);
      if(doc.safeToClose()) {
        desktop.remove(c);
        doc.unload();
      }
    }
    else
      desktop.remove(c);
    this.checkToolBar();
  }

  // public void fileExit(String s) {
  public void fileExit(Vector<Object> v) {
    if(unsavedFiles())
      return;
    dispose();
  }

  /**
   * Answers an InputSource on a file with the given name and suffix in the <B>src </B> subdirectory tree;
   * if none is found, shows an error dialog and answers <TT>null</TT>.
   *
   * @param docname The document name in the form <TT>filename.suffix</TT>.
   */
  public File getSource(String docname) {
    // System.out.println("[FB] getSource " + docname);
    // long stime = System.currentTimeMillis();
    File src = getSource(new File("src"), docname);
    // if(src == null)
    // JOptionPane.showMessageDialog(this, "Can't find source for " + docname + '.', "File Open Failed",
    // JOptionPane.WARNING_MESSAGE);
    // long etime = System.currentTimeMillis();
    // long ttime = etime - stime;
    // System.out.println("[FB] TOTAL getSource " + ttime + "ms");
    return src;
  }

  /**
   * Answers an InputSource on a file with the given name and suffix in the given subdirectory tree. If none
   * is found, answers <TT>null</TT>.
   *
   * @param dir The full directory of the file...
   * @param docname The document name in the form <TT>filename.suffix</TT>.
   */
  public static File getSource(File dir, String docname) {
    // TODO: THIS IS WHY FILES TAKE A WHILE to load.. ~1+ seconds JUST ON
    // THIS (give full path == 0ms vs 500ms!
    // long stime = System.currentTimeMillis();

    for(int i = 0; i < Constants.fbtTemplates.length; i++) {
      if(docname.equals(Constants.fbtTemplates[i])) {
        return new File(Constants.fbtTemplateFolder + docname);
      }
    }

    // try {
    // return new InputSource(new FileInputStream(new File(dir,docname)));
    File src = new File(dir, docname);
    if(src.exists())
      return src;
    // } catch (Exception e){//FileNotFoundException e) {
    // e.printStackTrace();
    File[] dirs = dir.listFiles(new FileFilter() {
      public boolean accept(File fl) {
        return fl.isDirectory();
      }
    });
    if(dirs != null) {
      for(int i = 0; i < dirs.length; i++) {
        if(!dirs[i].getName().equals("template") && !dirs[i].getPath().contains(".svn")) {
          src = getSource(dirs[i], docname);
          if(src != null) {
            // long etime = System.currentTimeMillis();
            // long ttime = etime - stime;
            // System.out.println("[FB] slower getSource end: " + ttime
            // +
            // "ms");
            return src;
          }
        }
      }
    }
    // e.printStackTrace();
    // }
    return null;
  }

  public static void main(String[] args) {

    // System.out.println(Constants.currentWorkingDirectory);

    try {
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    }
    catch(ClassNotFoundException e) {
      e.printStackTrace();
    }
    catch(InstantiationException e) {
      e.printStackTrace();
    }
    catch(IllegalAccessException e) {
      e.printStackTrace();
    }
    catch(UnsupportedLookAndFeelException e) {
      e.printStackTrace();
    }
    // FBench fBench =
    new FBench();
  }

  /**
   * Create a JMenuItem
   *
   * @param label Menu item name
   * @param actionCommand Action to be performed
   * @param iconName Icon to be displayed
   * @param toolTip Tool tip text
   * @param keyStroke
   * @return
   */
  private JMenuItem createMenuItem(String label, String actionCommand, String iconName, String toolTip,
      KeyStroke keyStroke) {
    JMenuItem item = new JMenuItem(label);
    item.addActionListener(this);
    item.setActionCommand(actionCommand);

    if(iconName != null && !iconName.isEmpty()) {
      item.setIcon(IconFactory.getIcon(iconName));
    }

    if(toolTip != null && !toolTip.isEmpty()) {
      item.setToolTipText(toolTip);
    }

    if(keyStroke != null) {
      item.setAccelerator(keyStroke);
    }

    return item;
  }

  /**
   * Create a JMenuItem
   *
   * @param label Menu item name
   * @param actionCommand Action to be performed
   * @param iconName Icon to be displayed
   * @param toolTip Tool tip text
   * @param accelerator
   * @param keyMask
   * @return
   */
  private JMenuItem createMenuItem(String label, String actionCommand, String iconName, String toolTip,
      Character accelerator, Integer keyMask) {

    JMenuItem item = null;

    if(accelerator != null && keyMask != null) {
      int keyMaskInt = Integer.valueOf(keyMask);
      item =
          createMenuItem(label, actionCommand, iconName, toolTip, KeyStroke
              .getKeyStroke(accelerator.charValue(), keyMaskInt));
    }
    else if(accelerator != null && keyMask == null) {
      item =
          createMenuItem(label, actionCommand, iconName, toolTip, KeyStroke
              .getKeyStroke(accelerator.charValue(), InputEvent.ALT_MASK));
    }
    else {
      item = createMenuItem(label, actionCommand, iconName, toolTip, null);
    }

    return item;
  }

  // TODO: Never USED
  public JCheckBoxMenuItem createMenuCheckBox(String label, String actionCommand) {
    JCheckBoxMenuItem item = new JCheckBoxMenuItem(label);
    item.addActionListener(this);
    item.setActionCommand(actionCommand);
    return item;
  }

  private void CompileSelected() {
    JTextArea textArea = getTextArea();
    boolean notNull = (textArea != null);
    compiletoJava.setEnabled(false);
    compiletoJavaDebug.setEnabled(false);
    if(notNull) {
      try {
        LibraryElementView launchView = (LibraryElementView) desktop.getSelectedComponent();
        if(launchView.getDocument().getDocumentElement().getNodeName().equals("FBType")) {
          compiletoJava.setEnabled(true);
          compiletoJavaDebug.setEnabled(true);
        }
      }
      catch(Exception e) {
      }
    }
  }

  private void runMenuSelected() {
    JTextArea textArea = getTextArea();
    boolean notNull = (textArea != null);
    runLaunchItem.setEnabled(notNull);
  }

  // private void DebugSelected() {
  // JTextArea textArea = getTextArea();
  // boolean notNull = (textArea != null);
  // debugItem.setEnabled(notNull);
  // debugPBItem.setEnabled(notNull);
  // }

  private void editMenuSelected() {
    JTextArea textArea = getTextArea();
    boolean notNull = (textArea != null);
    boolean textSelected = notNull && (textArea.getSelectionEnd() > textArea.getSelectionStart());

    editCutItem.setEnabled(textSelected);
    editCopyItem.setEnabled(textSelected);
    editPasteItem.setEnabled(notNull);
    editDeleteItem.setEnabled(textSelected);
    editFindReplaceItem.setEnabled(notNull);
    editSelectAllItem.setEnabled(notNull);

    // TODO: The undo and redo buttons are always disabled temporarily
    editUndoItem.setEnabled(false);
    editRedoItem.setEnabled(false);
  }

  /**
   * Returns the name of a suitable icon for use in menu items as determined by the suffix of the given file
   * name. If no suitable icon is found, returns the empty String.
   */

  public static String getIconForFile(String flnm) {
    int n = flnm.lastIndexOf('.');
    if((n <= 0) || (n >= flnm.length()))
      return "";
    String suffix = flnm.substring(n);
    String[] sfxs = getFileSuffixes();
    String[] icons = {"fb16", "fb16", "res16", "dev16", "system", "file_obj", "xmlObject", "file_obj"};
    for(int i = 0; i < Math.min(sfxs.length, icons.length); i++) {
      if(suffix.equals(sfxs[i]))
        return icons[i];
    }
    return "";
  }

  /** Returns a list of suitable suffixes for IEC 61499 LibraryElement files. */
  public static String[] getFileSuffixes() {
    String[] ans = {".fbt", ".adp", ".res", ".dev", ".sys", ".dtp", ".xml", ".src", ".db", ".trace"};
    return ans;
  }

  /**
   * Opens the document with the given filename in a new EditorFrame unless already open; in any case
   * transfers focus to the EditorFrame of the given file. If none can be found or created, exits with all
   * frames iconified.
   */
  public void open(String filename) {
    if(show(filename))
      return;
    Document doc = Library.getDocument(filename);

    if(doc == null) {
      JOptionPane.showMessageDialog(this, "Can't find source for " + Library.getFullDocPath(filename)
          + '.', "File Open Failed", JOptionPane.WARNING_MESSAGE);
      return;
    }
    final LibraryElementView newView = new LibraryElementView(doc);
    newView.getGraphView().setTransferHandler(gvhandler);

    desktop.addTab(newView.getName(), newView);
    desktop.setSelectedComponent(newView);

    final TabPanel newTabPanel = new TabPanel(newView.getName(), desktop, newView);
    newTabPanel.addMouseListener(new MouseAdapter() {
      public void mouseClicked(MouseEvent e) {
        if(e.getClickCount() == 1) {
          desktop.setSelectedComponent(newView);
        }
        else if(e.getClickCount() > 1) {
          if(newView.safeToClose()) {
            desktop.remove(desktop.getSelectedComponent());
          }
          checkToolBar();
        }
      }
    });
    desktop.setTabComponentAt(desktop.getSelectedIndex(), newTabPanel);

    checkToolBar();
  }

  // public void FileOpen(String txt){
  public void FileOpen(Vector<Object> v) {
    select_item.setDialogTitle("Open A File (IEC 61499 Compatible)");
    select_item.setFileFilter(new FBLibrary());
    select_item.setFileView(new FBIconLibrary());
    int choice = select_item.showOpenDialog(this);
    if(choice != 0)
      return;
    File f = select_item.getSelectedFile();
    if(f == null)
      return;
    open(f);
  }

  // TODO Name of the file = Name in the first element of the document
  // TODO Location of the file = specified in CompilerInfo - Somehow related
  // with Project?
  // public void fileSaveAsXML(String s) {
  public void fileSaveAsXML(Vector<String> v) {
    LibraryElementView launchView = (LibraryElementView) desktop.getSelectedComponent();
    if(launchView == null)
      return;

    launchView.saveXML();

    desktop.repaint();
  }

  /** gsha041: Strip a file path to give the classPath only */
  public static String stripPath(String s) {
    int start = s.indexOf("src" + File.separator) + 4;
    int end = s.lastIndexOf(File.separator);
    if(start != -1 && end != -1) {
      if(start < end)
        return new String(s.substring(start, end));
      else
        return new String(s.substring(end + 1));
    }
    else if(start > end)
      return new String();
    else
      return new String(s);
  }

  /** gsha041: Strip Compiler info attribute to give the classPath only */
  public static String stripCompilerInfo(String s) {
    int start = s.indexOf("fb.rt") + 5;
    int end = s.indexOf(";");
    if(s.charAt(start) == '.')
      start += 1;
    return new String(s.substring(start, end));
  }

  public static String getSourceType(Document document) {
    String clist = document.getFirstChild().getNodeName();
    String type = "";
    if(clist.equals("FBType")) {
      type = ".fbt";
    }
    else if(clist.equals("Device")) {
      type = ".dev";
    }
    else if(clist.equals("System")) {
      type = ".sys";
    }
    else if(clist.equals("DataType")) {
      type = ".dtp";
    }
    else if(clist.equals("AdapterType")) {
      type = ".adp";
    }
    else if(clist.equals("ResourceType")) {
      type = ".res";
    }
    return type;
  }

  public static Hashtable<String, String> getGraphModels() {
    return graphModels;
  }

  public static void putGraphModel(String name, String className) {
    graphModels.put(name, className);
  }

  public static String getGraphModel(String name) {
    return graphModels.get(name);
  }

  public static Hashtable<String, String> getGraphElements() {
    return graphElements;
  }

  public static void putGraphElement(String name, String className) {
    graphElements.put(name, className);
  }

  public static String getGraphElement(String name) {
    return graphElements.get(name);
  }

  public static Hashtable<String, String> getMutationListeners() {
    return mutationListeners;
  }

  public static void putMutationListener(String name, String className) {
    mutationListeners.put(name, className);
  }

  public static String getMutationListener(String name) {
    return mutationListeners.get(name);
  }

  public static Hashtable<String, String> getTreeNodes() {
    return treeNodes;
  }

  public static void putTreeNode(String name, String className) {
    treeNodes.put(name, className);
  }

  public static String getTreeNode(String name) {
    return treeNodes.get(name);
  }

  public static Hashtable<String, String[]> getTreeMenus() {
    return treeMenus;
  }

  public static void putTreeMenu(String name, String[] menuOptions) {
    treeMenus.put(name, menuOptions);
  }

  public static String[] getTreeMenu(String name) {
    return treeMenus.get(name);
  }

  public static Hashtable<String, String> getTreeMenuActions() {
    return treeMenuActions;
  }

  public static void putTreeMenuAction(String name, String className) {
    treeMenuActions.put(name, className);
  }

  public static String getTreeMenuAction(String name) {
    return treeMenuActions.get(name);
  }

  public String getSourceType(LibraryElementView launchView) {
    String clist = launchView.getDocument().getFirstChild().getNodeName();
    String type = "";
    if(clist.equals("FBType")) {
      type = ".fbt";
    }
    else if(clist.equals("Device")) {
      type = ".dev";
    }
    else if(clist.equals("System")) {
      type = ".sys";
    }
    else if(clist.equals("DataType")) {
      type = ".dtp";
    }
    else if(clist.equals("AdapterType")) {
      type = ".adp";
    }
    else if(clist.equals("ResourceType")) {
      type = ".res";
    }
    return type;
  }

  public Document getSelectedDoc() {
    LibraryElementView launchView = (LibraryElementView) desktop.getSelectedComponent();
    if(launchView == null)
      return null;

    return launchView.getDocument();
  }

  public LibraryElementView getSelectedView() {
    LibraryElementView launchView = (LibraryElementView) desktop.getSelectedComponent();
    return launchView;
  }

  public void fileSaveAsJavaDebug(Vector<Object> v) {
    LibraryElementView launchView = (LibraryElementView) desktop.getSelectedComponent();
    String contents =
        new DOMTranslationModel(launchView.getDocument(), null, "DOMtoJavaDebug.xsl", "Java")
            .performTranslation();
    saveJava(launchView, contents);
  }

  // public void fileSaveAsJava(String s) {
  public void fileSaveAsJava(Vector<Object> v) {
    LibraryElementView launchView = (LibraryElementView) desktop.getSelectedComponent();
    int selectedRow = launchView.getSelectedTreeRow(); // Save the selected
    // element so we can
    // put it back
    launchView.setSelectedTreeRow(0); // Select the first treenode so the
    // full source is compiled.
    String contents = launchView.getJavaArea().getText();
    saveJava(launchView, contents);
    launchView.setSelectedTreeRow(selectedRow);
  }
   
  private void saveJava(LibraryElementView launchView, String contents) {
    String filename = launchView.getDocument().getDocumentElement().getAttribute("Name") + ".java";
    String path =
        launchView.getDocument().getElementsByTagName("CompilerInfo").item(0).getAttributes()
            .getNamedItem("header").getNodeValue();
    contents = removeHTML(contents);
    path = removePath(path);
    // String rtPath = "rt" + File.separator + "fb" + File.separator + "rt" + File.separator;

    String rtPath = adjustCommand(preferences.getProperty("rtPath"));
    if(rtPath == null)
      rtPath = "rt\\fb\\rt".replace('\\', File.separatorChar);
    File path_check = new File(rtPath + path);

    if(!path_check.exists())
      path_check.mkdirs(); // Should also create any non-exist directories as well

    File f = new File(rtPath + path, filename);
    try {
      if(f.exists()) {
        f.delete();
        f.createNewFile();
      }
      FileWriter fw = new FileWriter(f);
      fw.write(contents);
      fw.close();
      Compiler cdlg = new Compiler(this);
      cdlg.showCentered();
      preferences.load(new FileInputStream("preferences.ini"));

      // String cmd = adjustCommand(preferences.getProperty("javac") + " -classpath ./rt;./fbrt.jar;.;
      // ");
     
      rtPathRoot = rtPath.subSequence(0, rtPath.indexOf(File.separatorChar)).toString();
      String cmd =
        adjustCommand(preferences.getProperty("javac"))
            // commented out by VV: reason command line in preferences.ini can explicitly include ./lib
            + " -classpath " + preferences.getProperty("classpath") ;
        //+ ";./fbrt.jar;.; ");

      cdlg.compile(f, cmd);
    }
    catch(IOException e) {
      System.err.println(e.getMessage());
      System.err.println("File " + f.getPath() + " FILE NOT SAVED.");
    }
  }

  public static String adjustCommand(String cmd) {
    String ans = cmd.replace(';', File.pathSeparatorChar);
    ans = ans.replace(':', File.pathSeparatorChar);
    ans = ans.replace('\\', File.separatorChar);
    ans = ans.replace('/', File.separatorChar);
    ans = ans.replaceFirst("\\;\\\\", "\\:\\\\");
    return ans;
  }

  public String removePath(String s) {
    if(s.contains("fb.rt.")) {
      int start = s.indexOf("fb.rt.") + 6;
      int end = s.indexOf(";");
      return new String(s.substring(start, end));
    }
    return s;
  }

  public static String removeHTML(String s) {
    s = s.replace("<br>", "\n");
    s = s.replace("<BR>", "\n");
    s = s.replace("&quot;", "\"");
    s = s.replace("&gt;", ">");
    s = s.replace("&lt;", "<");
    s = s.replace("&amp;", "&");
    s = s.replace("&#34;", "\"");
    s = s.replace("&#10;", "\n");
    s = s.replace("&#60;", "<");
    s = s.replace("&#62;", ">");
    s = s.replace("&#38;", "&");
    s = new String(s);
    if(s.contains("<body>")) {
      int start = s.indexOf("<body>") + 6;
      int end = s.indexOf("</body>");
      s = s.substring(start, end);
    }
    return s;
  }

  public void launch(String cmd) {
    try {
      Process p = Runtime.getRuntime().exec(cmd);
      p.waitFor();
      processes.put(cmd, p);
    }
    catch(IOException iox) {
      String msg[] = {"Can't open the Java runtime."};
      JOptionPane.showMessageDialog(this, msg, "Can't open Java runtime", 2);
    }
    catch(InterruptedException e) {
    }
  }

  public void teminate(Process p) {
    p.destroy();
    p = null;
  }

  String launchPath = null;

  public void runLaunch(Vector<Object> v) {

    LibraryElementView launchView = (LibraryElementView) desktop.getSelectedComponent();

    Document document = launchView.getDocument();
    String keyword = document.getDocumentElement().getNodeName();
    String file = document.getDocumentElement().getAttribute("Name");

    if(keyword.equals("FBType"))
      file = file + ".fbt";
    else if(keyword.equals("System"))
      file = file + ".sys";
    else {
      System.out.println("UNSUPPORTED TYPE FOR LAUNCH");
      return;
    }

    // String path = Library.getFilePath(document);
    File f = this.getSource(file);
    // if(path == null) {
    // System.out.println("Invalid path.");
    // return;
    // }

    String path = f.getPath();
    if(f.isAbsolute())
      path = path.replace(System.getProperty("user.dir") + File.separatorChar, "");
    if(!path.startsWith("src"))
      path = "src/".replace('/', File.separatorChar) + path;
    launchPath = path;   

    int port = 61502;
    String hostIp = "localhost";

    try {
      Properties debugPreferences = new Properties();
      debugPreferences.load(new FileInputStream("debug.ini"));
      port = Integer.parseInt(debugPreferences.getProperty("port", "61502"));
      hostIp = debugPreferences.getProperty("host", "localhost");
    }
    catch(FileNotFoundException e1) {
    }
    catch(IOException e1) {
    }

    FBInstance.debugHost = hostIp + ":" + port;

    try {
      Runnable runnable = new Runnable() {
        public void run() {
          try {
            String file = new File(launchPath).getName();

            int port = 61502;
            String hostIp = "localhost";

            try {
              Properties debugPreferences = new Properties();
              debugPreferences.load(new FileInputStream("debug.ini"));
              port = Integer.parseInt(debugPreferences.getProperty("port", "61502"));
              hostIp = debugPreferences.getProperty("host", "localhost");
            }
            catch(FileNotFoundException e1) {
            }
            catch(IOException e1) {
            }

            // FBInstance.localDebugHost = hostIp + ":" + port;
            // FBInstance.debugHost = hostIp + ":" + port;

            // Process proc =
            // Runtime.getRuntime().exec("java -classpath ./rt;./fbrt.jar;
            // fb.rt.tools.SystemManager "
            // + launchPath);

            String rtPath = adjustCommand(preferences.getProperty("rtPath"));
            String rtPathRoot =
                rtPath.subSequence(0, rtPath.indexOf(File.separatorChar)).toString();

            String cmd =
                "java -classpath " + "\"" + "./" + rtPathRoot + ";./fbrt.jar;"
                    + System.getProperty("java.class.path") + "\" "
                    + "fbench.FBenchSystemManager -d " + hostIp + ":" + port + " "
                    + launchPath;

            Process proc = Runtime.getRuntime().exec(cmd);
            StreamLogger out = new StreamLogger(proc.getInputStream(), false, file + " output");
            StreamLogger err = new StreamLogger(proc.getErrorStream(), true, file + " error");

            out.start();
            err.start();

            processes.put(launchPath, proc);
            int exitCode = proc.waitFor();
            System.out.println(file + " Launch process exited: " + exitCode);

            out.stop = true;
            err.stop = true;
            out.interrupt();
            err.interrupt();
          }
          catch(Exception e) {
            e.printStackTrace();
          }
        }
      };

      if(processes.containsKey(launchPath)) {
        processes.get(launchPath).destroy();
        processes.remove(launchPath);
      }
      new Thread(runnable, file + " Launch process").start();
    }
    catch(Exception e) {
      // logger.log(e);
      // System.exit(-1);
    }
  }

  public void log(String s) {
  }

  public void log(Exception e) {
  }

  /**
   * Opens a document from the given file in a new EditorFrame unless already open; in any case transfers
   * focus to the EditorFrame of the given file. If none can be found or created, exits with all frames
   * iconified.
   */
  public void open(File f) {
    if(!f.isFile()) {
      JOptionPane.showMessageDialog(this, f.getAbsolutePath() + " is not a File.", "No Such File",
                      JOptionPane.WARNING_MESSAGE);
      return;
    }
    String flnm = f.getName();
    if(show(flnm))
      return;
    Library.load(f);
    open(flnm);
  }

  public void createViewFrame() {
    LibraryTreeNode libraryRoot = new LibraryTreeNode(new File("src"), null);
    final JTree libraryTree = new JTree(libraryRoot);
    gvhandler = new GraphViewTransfer(libraryTree);
    libraryTree.setCellRenderer(libraryRoot);
    libraryTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
    libraryTree.setDragEnabled(true);
    libraryTree.addMouseListener(new MouseAdapter() {
      public void mouseClicked(MouseEvent e) {
        if(e.getClickCount() == 2) {
          Object obj = null;
          if(libraryTree.getLeadSelectionPath() != null)
            obj = libraryTree.getLeadSelectionPath().getLastPathComponent();
          if(obj instanceof LibraryTreeNode)
            open(((LibraryTreeNode) obj).getFile());
        }
        else if(e.getButton() == 3) {
          refresh_view.setLocation(e.getX() + viewFrame.getX(), e.getY() + viewFrame.getY());
          refresh_view.setVisible(true);
        }
        else {
          refresh_view.setVisible(false);
        }
      }
    });
    JScrollPane libraryView = new JScrollPane(libraryTree);
    viewFrame.setIconImage(IconFactory.getIcon("fbench24.png").getImage());
    viewFrame.setBounds(900, 100, 250, 600);
    viewFrame.getContentPane().add(libraryView);
    viewFrame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        treeViewMenu.setSelected(false);
      }
    });
    viewFrame.setVisible(true);
  }

  public void reloadLibraryTree(Vector<Object> v) {
    refresh_view.setVisible(false);
    viewFrame.dispose();
    createViewFrame();
  }

  public void runViewMenu(Vector<Object> v) {
    if(viewFrame.getContentPane().getComponentCount() == 0 && treeViewMenu.isSelected()) {
      createViewFrame();
    }
    else if(treeViewMenu.isSelected()) {
      viewFrame.setVisible(true);
    }
    else if(!treeViewMenu.isSelected()) {
      viewFrame.setVisible(false);
    }
  }

  public void menuDeselected(MenuEvent e) {
  }

  public void menuCanceled(MenuEvent e) {
  }

  // public void editAction(String lbl) {
  public void editAction(Vector<Object> v) {
    String lbl = (String) v.get(0);
    JTextArea textarea = getTextArea();
    if(textarea == null)
      return;
    if(lbl.equals("Cut")) {
      textarea.cut();
    }
    else if(lbl.equals("Copy")) {
      textarea.copy();
    }
    else if(lbl.equals("Paste")) {
      textarea.paste();
    }
    else if(lbl.equals("Delete")) {
      textarea.replaceSelection("");
    }
    else if(lbl.startsWith("Find")) {
      System.out.println("Find/Replace");
    }
    else if(lbl.equals("Undo")) {
      System.out.println("Undo");
    }
    else if(lbl.equals("Redo")) {
      System.out.println("Redo");
    }
  }

  /*
   * public void EventChanged(DebugEvent event) { debugFBs(event.getdebugname()); }
   */

  /**
   * If an EditorFrame is selected and not iconified, return its text area; otherwise return <TT>null</TT>.
   */
  public JTextArea getTextArea() {
    Component fr = desktop.getSelectedComponent();
    return (fr == null) ? null : ((LibraryElementView) fr).getXmlArea();
  }

  public JTabbedPane getDesktop() {
    return desktop;
  }

  public Hashtable<String, Object> getInstances() {
    return instances;
  }

  private void setupPreferences() {
    try {
      preferences.load(new FileInputStream("preferences.ini"));
    }
    catch(IOException e) {
      System.out.println("Error reading preferences: " + e.getMessage());
    }
    // preferences.list(System.out);
  }

  public void newCFB(Vector<Object> v) {
    open("Composite.fbt");
  }

  public void newBFB(Vector<Object> v) {
    open("Basic.fbt");
  }

  public void newProxy(Vector<Object> v) {
    open("Proxy.fbt");
  }

  public void newSI(Vector<Object> v) {
    open("ServiceInterface.fbt");
  }

  public void newSimple(Vector<Object> v) {
    open("Simple.fbt");
  }

  public void newAdapt(Vector<Object> v) {
    open("AdapterType.adp");
  }

  public void newRes(Vector<Object> v) {
    open("ResourceType.res");
  }

  public void newDev(Vector<Object> v) {
    open("DeviceType.dev");
  }

  public void newSys(Vector<Object> v) {
    open("System.sys");
  }

  public void newArray(Vector<Object> v) {
    open("Array.dtp");
  }

  public void newDirect(Vector<Object> v) {
    open("Direct.dtp");
  }

  public void newEnu(Vector<Object> v) {
    open("Enumerated.dtp");
  }

  public void newStruct(Vector<Object> v) {
    open("Structured.dtp");
  }

  public void newSubrange(Vector<Object> v) {
    open("Subrange.dtp");
  }

  class StreamLogger extends Thread {
    private InputStream is;

    private PrintStream out;

    public boolean stop = false;

    public StreamLogger(InputStream stream, boolean error, String threadName) {
      super(threadName);

      this.is = stream;
      if(error)
        out = System.err;
      else
        out = System.out;
    }

    public void run() {
      try {
        InputStreamReader isr = new InputStreamReader(is);
        BufferedReader br = new BufferedReader(isr);
        String line = null;
        while(!stop && (line = br.readLine()) != null)
          out.println(line);
      }
      catch(IOException e) {
        e.printStackTrace();
      }
    }
  }

  private class simpleMouseAdapter extends MouseAdapter {
    private String link = null;

    public simpleMouseAdapter(String link) {
      this.link = link;
    }

    public void mousePressed(MouseEvent e) {
      // JOptionPane.showMessageDialog(null, link);
      try {
        Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " + link);
      }
      catch(IOException ex) {
        JOptionPane.showMessageDialog(null, ex.getMessage(), "Error opening " + link,
                        JOptionPane.WARNING_MESSAGE);
      }
    }
  }

  public void showHelpOperation(String preferredBrowser, String manualURL) {
    String osName = System.getProperty("os.name");
    try {
      if(preferredBrowser != null) {
        Runtime.getRuntime().exec(new String[]{preferredBrowser, manualURL});
      }
      else {

        if(osName.startsWith("Mac OS")) {
          Class<?> fileMgr = Class.forName("com.apple.eio.FileManager");
          Method openURL = fileMgr.getDeclaredMethod("openURL", new Class<?>[]{String.class});
          openURL.invoke(null, new Object[]{manualURL});
        }
        else if(osName.startsWith("Windows"))
          Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " + manualURL);
        else { // assume Unix or Linux
          String[] browsers = {"firefox", "opera", "konqueror", "epiphany", "mozilla", "netscape"};
          String browser = null;

          for(int count = 0; count < browsers.length && browser == null; count++) {
            if(Runtime.getRuntime().exec(new String[]{"which", browsers[count]}).waitFor() == 0) {
              browser = browsers[count];
            }
          }

          if(browser == null) {
            JOptionPane
                .showMessageDialog(this,
                          "Can't locate an browser, please manually open the ViEd Manual.htm inside the ViEd folder");
          }
          else {
            Runtime.getRuntime().exec(new String[]{browser, manualURL});
          }
        }
      }
    }
    catch(Exception e) {
      JOptionPane.showMessageDialog(this, e.getMessage(), "Error opening " + manualURL,
                      JOptionPane.WARNING_MESSAGE);
    }
  }

  public int help(Vector<String> v) {
    String topic = (String) v.get(0);
    if(topic.startsWith("About")) {
      // JLabel msg =
      // new JLabel(
      // "<HTML><CENTER><P>"
      // + FBench.productID
      // + " Version "
      // + FBench.version
      // + "<BR><BR>An Open Source Project of the OOONEIDA"
      // + "<BR>Developed By The University of Auckland"
      // + "<BR><A HREF=\"http://www.ece.auckland.ac.nz\">Department of
      // Electrical and Computer Engineering</A></P>"
      // + "<BR><BR>By clicking &quot;OK&quot; you agree to use this
      // software"
      // + "<BR>under the provisions of the Common Public License"
      // + "<BR><A
      // HREF=\"http://opensource.org/licenses/cpl1.0.php\">&lt;http://www.opensource.org/cpl1.0.php&gt;</A>."
      // + "<BR><BR>To contribute to this project go to"
      // + "<BR><A
      // HREF=\"http://sourceforge.net/projects/oooneida-fbench/\">FBench
      // Project</A>."
      // + "</CENTER></HTML>");
      // msg.setBackground(Color.lightGray);

      JLabel aboutMsg1 =
          new JLabel("<HTML><CENTER><P><BR><BR><BR>" + FBench.productID + " Version "
              + FBench.version + "<BR><BR>An Open Source Project of the OOONEIDA"
              + "<BR>Developed By The University of Auckland" + "</P></CENTER></HTML>");
      JLabel aboutMsg2 =
          new JLabel(
              "<HTML><CENTER><BR><BR>By clicking &quot;OK&quot; you agree to use this software"
                  + "<BR>under the provisions of the Common Public License"
                  + "</CENTER></HTML>");
      JLabel aboutMsg3 =
          new JLabel(
              "<HTML><CENTER><BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;To contribute to this project go to"
                  + "</CENTER></HTML>");

      String cplURL = "http://opensource.org/licenses/cpl1.0.php";
      String eceURL = "http://www2.ece.auckland.ac.nz/";
      String fbURL = "http://sourceforge.net/projects/oooneida-fbench/";
      JLabel cpLicence =
          new JLabel("<HTML><CENTER><A HREF=\"" + cplURL + "\">" + cplURL + "</A></CENTER></HTML>");
      JLabel eceDepartment =
          new JLabel("<HTML><CENTER><A HREF=\"" + eceURL
              + "\">Department of Electrical and Computer Engineering</A></CENTER></HTML>");
      JLabel fbProject =
          new JLabel("<HTML><CENTER><A HREF=\"" + fbURL + "\">" + fbURL + "</A></CENTER></HTML>");

      aboutMsg1.setBackground(Color.lightGray);
      aboutMsg2.setBackground(Color.lightGray);
      aboutMsg3.setBackground(Color.lightGray);
      eceDepartment.setBackground(Color.lightGray);
      cpLicence.setBackground(Color.lightGray);
      fbProject.setBackground(Color.lightGray);

      JPanel aboutJPanel = new JPanel();
      aboutJPanel.setLayout(new BoxLayout(aboutJPanel, BoxLayout.Y_AXIS));
      aboutJPanel.add(aboutMsg1);
      aboutJPanel.add(eceDepartment);
      aboutJPanel.add(aboutMsg2);
      aboutJPanel.add(cpLicence);
      aboutJPanel.add(aboutMsg3);
      aboutJPanel.add(fbProject);

      cpLicence.addMouseListener(new simpleMouseAdapter(cplURL));
      cpLicence.setCursor(new Cursor(Cursor.HAND_CURSOR));

      eceDepartment.addMouseListener(new simpleMouseAdapter(eceURL));
      eceDepartment.setCursor(new Cursor(Cursor.HAND_CURSOR));

      fbProject.addMouseListener(new simpleMouseAdapter(fbURL));
      fbProject.setCursor(new Cursor(Cursor.HAND_CURSOR));

      return JOptionPane.showConfirmDialog(this, aboutJPanel, "About " + FBench.productID,
                          JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_OPTION,
                          IconFactory.getIcon("fbench0.jpg"));
    }

    if(topic.equals("User Manual"))
      topic = Constants.fbenchUserManual;
    else if(topic.equals("Developer's Guide"))
      topic = Constants.fbenchDevelopersGuide;
    String[] cmd = new String[2];
    cmd[0] = preferences.getProperty("browser");
    cmd[1] = topic;

    showHelpOperation(cmd[0], cmd[1]);

    return 0;
  }

  /**
   * If a file with the given name is already open in a tabbed pane, brings that tab to the top.
   *
   * @param filename, e.g., <TT>X2Y2.fbt</TT> (the suffix is ignored).
   * @return <TT>true</TT> if an open file was found.
   */
  protected boolean show(String filename) {

    int n = filename.indexOf('.');
    if(n > 0) {
      filename = filename.substring(0, n);
    }

    for(int i = 0; i < desktop.getComponentCount(); i++) {
      Component c = desktop.getComponent(i);
      String cName = c.getName();
      if(cName != null && c.getName().equals(filename)) {
        desktop.setSelectedComponent(c);
        return true;
      }
    }
    return false;
  }

  class ActionSet extends AbstractAction {

    private static final long serialVersionUID = 3178916632987292161L;

    public ActionSet(String name, Icon icon) {
      super(name, icon);
    }

    public void actionPerformed(ActionEvent e) {
      String command = e.getActionCommand();
      if(command.equals("Parse XML")) {
        setStatusText("Parsing XML");
        ((LibraryElementView) desktop.getSelectedComponent()).reparse();
        setStatusText("Parsed");
      }
      else if(command.equals("Close Tab")) {
        // // See if modified
        // if (desktop.getSelectedComponent() instanceof
        // LibraryElementView) {
        // LibraryElementView docView = (LibraryElementView) desktop
        // .getSelectedComponent();
        // if (docView.modified()) {
        // int value = JOptionPane.showConfirmDialog(null,
        // "Save before close?", "Save before close?",
        // JOptionPane.YES_NO_CANCEL_OPTION);
        // if (value == JOptionPane.CANCEL_OPTION) {
        // // Do nothing
        // return;
        // }
        // if (value == JOptionPane.YES_OPTION) {
        // // if yes.. save it
        // Vector<String> args = new Vector<String>();
        // args.add(desktop.getSelectedComponent().getName());
        // fileSaveAsXML(args);
        // }
        // // if no just close
        // }
        // // TODO: Redo!!!!
        // // docView.unload();
        // }
        // // if no just close
        // desktop.remove(desktop.getSelectedComponent());
        // checkToolBar();
        closeTab(desktop.getSelectedComponent());
      }
      else if(command.equals("Save Now")) {
        Vector<String> args = new Vector<String>();
        LibraryElementView doc = (LibraryElementView) desktop.getSelectedComponent();
        args.add(desktop.getSelectedComponent().getName());
        fileSaveAsXML(args);
        setStatusText("File saved in " + doc.getSavePath());
      }
      else if(command.equals("Next Tab")) {
        int selectedIndex = desktop.getSelectedIndex();
        if(selectedIndex < desktop.getTabCount() - 1)
          desktop.setSelectedIndex(selectedIndex + 1);
        checkToolBar();
      }
      else if(command.equals("Previous Tab")) {
        int selectedIndex = desktop.getSelectedIndex();
        if(selectedIndex > 0)
          desktop.setSelectedIndex(selectedIndex - 1);
        checkToolBar();
      }
    }
  }

  public Properties getProps() {
    return preferences;
  }

  public PluginManager getPluginManager() {
    return plugin;
  }

  public static String chooseFolderPath() {
    FBench fbench = FBench.theBench;
    fbench.select_item.setDialogTitle("Open A File (IEC 61499 Compatible)");
    fbench.select_item.setFileFilter(new FBLibrary());
    fbench.select_item.setFileView(new FBIconLibrary());
    fbench.select_item.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
    int choice = fbench.select_item.showOpenDialog(fbench);
    fbench.select_item.setFileSelectionMode(JFileChooser.FILES_ONLY);
    if(choice != 0)
      return null;
    File f = fbench.select_item.getSelectedFile();
    if(f != null)
      return f.getPath();
    return null;
  }
}
TOP

Related Classes of fbench.FBench$StreamLogger

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.