/*
 * BIFrame.java
 *
 * Copyright (c) 2002, 2003, Oracle Corporation. All rights reserved. Oracle grants
 * you ("Licensee") a non-exclusive, royalty-free, worldwide license to use,
 * modify and redistribute this software in source and binary code form, provided
 * that (i) this copyright notice and license appear on all copies of the
 * software; (ii) Licensee does not utilize the software in a manner disparaging
 * to Oracle; and (iii) Licensee does not utilize the software in a manner that
 * violates the terms of any Licensee agreement with Oracle.
 */
package samples.javaclient;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Frame;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.net.URL;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.swing.BorderFactory;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTree;
import javax.swing.JWindow;
import javax.swing.UIManager;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.text.Position;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.event.MenuEvent;
import javax.swing.event.MenuListener;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import oracle.bali.ewt.util.WindowUtils;
import oracle.bali.ewt.olaf.OracleLookAndFeel;
import oracle.dss.appmodule.client.BISession;
import oracle.dss.appmodule.client.BISessionException;
import oracle.dss.bicontext.ManagerFactory;
import oracle.dss.connection.client.Connection;
import oracle.dss.connection.common.ConnectionException;
import oracle.dss.dataSource.client.QueryManager;
import oracle.dss.dataSource.common.Query;
import oracle.dss.dataSource.common.QueryException;
import oracle.dss.metadataManager.client.MetadataManager;
import oracle.dss.metadataManager.common.MetadataManagerException;
import oracle.dss.metadataManager.common.MM;
import oracle.dss.persistence.persistencemanager.common.PersistenceManager;
import oracle.dss.security.BIUser;
import oracle.dss.selection.SelectionException;
import oracle.dss.selection.step.InvalidStepArgException;
import oracle.dss.util.gui.BIExceptionDialog;

/**
 * The main class for the BIFrame sample. 
 * <P>
 * The BIFrame is essentially a JFrame that provides a menu with access to 
 * the samples. It automatically connects to the OLAP service and the BI Beans
 * catalog on startup based on information in the BIConfig file
 * The other samples also have access to the BISession instance and the
 * MetadataManager instance through the provided methods.
 */
public class BIFrame extends JFrame {
  // the name of the configuration file
  private static final String m_configFile = "/javaclientOLAPConfig1.xml";

  private JMenuBar m_menuBar;          // the menu bar
  private JLabel m_statusBar;          // the status bar
  private JPanel m_displayPanel;       // the center panel inside the JFrame
  private String m_status;             // status of application
  private Hashtable m_descriptions;    // sample descriptions
  
  // the user session
  private BISession m_session;

  // the MetadataManager for the session
  private MetadataManager m_metadataManager;

  // the PersistenceManager for the session
  private PersistenceManager m_persistenceManager;

  // the QueryManager for the session
  private QueryManager m_queryManager; 
  
  // the default query
  private Query m_query;               
 
  // the sample labels
  private static final String m_mainLabel = "BI Beans Java Client Samples";
  private static final String m_queryMainLabel = "Query";
  private static final String m_presentationMainLabel = "Presentation";
  private static final String m_catalogMainLabel = "Catalog";
  private static final String m_calcLabel = "Creating calculations";
  private static final String m_exportLabel = "Exporting presentations";
  private static final String m_linkingLabel = "Linking presentations";
  private static final String m_catalogLabel = "Using BI Beans Catalog";
  private static final String m_metadataLabel = "Browsing metadata";
  private static final String m_graphLabel = "Modifying graphs";
  private static final String m_newPresLabel = "Custom presentation wizard";
  private static final String m_printLabel = "Printing crosstabs";
  private static final String m_dimListLabel = "Using dimension lists";
  private static final String m_rulesLabel = "Formatting crosstabs";
  private static final String m_querybuilderLabel = "Using querybuilder";
  private static final String m_writebackLabel = "Writeback data";
  
  // the sample classes
  private BICalc m_biCalc;             
  private BIExport m_biExport;
  private BILinking m_biLinking;
  private BICatalog m_biCatalog;
  private BIMetadata m_biMetadata;
  private BIGraph m_biGraph;
  private BINewPres m_biNewPres;
  private BIPrint m_biPrint;
  private BIDimList m_biDimList;
  private BIRules m_biRules;
  private BIQuerybuilder m_biQuerybuilder;
  private BIWriteback m_biWriteback;

  public BIFrame() {
    super();
    init();
  }

  /**
   * Constructor for BIFrame.
   *
   * @param title The title of the JFrame.
   */
  public BIFrame(String title) {
    super(title);

    // set the default look and feel to OracleLookAndFeel
    try {
      UIManager.setLookAndFeel(new OracleLookAndFeel());
    }
    catch (Exception landfex) {
      showExceptionDialog(this, landfex);
    }

    init();
    
  }

  /**
   * Main method for BIFrame
   */
  public static void main(String args[]) {
    BIFrame bif = new BIFrame("BI Beans Java Client Samples");
    bif.setSize(800, 650);
    bif.setVisible(true);
  }

  /**
   * Overrides the setVisible method from JComponent to allow the centering of
   * the BIFrame before displaying it
   *
   * @param visible <code>true</code> if BIFrame should be made visible.
   *                <code>false</code> otherwise.
   */
  public void setVisible(boolean visible) {
    // center the frame
    WindowUtils.centerWindow(this);
    super.setVisible(visible);
  }

  /**
   * Connects to the OLAP service and BI Beans Catalog using connection
   * information from the BI Configuration file and from the BIConectionDialog.
   *
   */
  protected void connect() {
    // output a message
    System.out.print("Connecting to the OLAP and BI Beans Catalog...");
    // creates a BISession for the current user session using a BI
    // Configuration file
    m_session = new BISession(m_configFile);
    
    // retrieves the MetadataManager from the ManagerFactory
    // the MetadataManager and its associated Connection(s) are defined in the
    // BI Configuration file
    // note that you could also define these objects programmatically as well.
    // consult the documentation for details
    try {
      ManagerFactory factory = m_session.getManagerFactory();

      m_metadataManager = (MetadataManager)factory.lookupManager(
                            ManagerFactory.METADATA_MANAGER, null, true);
      m_queryManager = (QueryManager)factory.lookupManager(
                         ManagerFactory.QUERY_MANAGER, null, true);
      m_persistenceManager = (PersistenceManager)factory.lookupManager(
                               ManagerFactory.PERSISTENCE_MANAGER, null, true);

      // output a message
      System.out.print("Success");
    }
    catch (BISessionException bse) {
      showExceptionDialog(this, bse);
    }
    catch (MetadataManagerException mme) {
      showExceptionDialog(this, mme);
    }
    catch (Exception ex) {
      showExceptionDialog(this, ex);
    }
  }

  /**
   * Disconnect the application from the MetadataManager and its associated
   * connections.  Disconnect the current user session.
   * Subclasses should override this method to add additional cleanup code.
   */
  protected void disconnect() {
    try {
      // detach from MetadataManager and disconnect the current session
      m_session.disconnect();

      // clean up
      m_session = null;
      m_metadataManager = null;
      m_queryManager = null;
      m_persistenceManager = null;
    }
    catch (BISessionException ex) {
      showExceptionDialog(this, ex);
    }
  }
  
  /*
   * Run the calc sample
   */
  protected void runCalcSample() {
    
    if (m_biCalc==null||!m_biCalc.isVisible()) {
      this.setCursor(new Cursor(Cursor.WAIT_CURSOR));
      m_biCalc = new BICalc(this, m_status);
      this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
    }
    m_biCalc.setSize(700, 550);  
    WindowUtils.centerWindow(m_biCalc);
    m_biCalc.setVisible(true);
  }

  /*
   * Run the export sample
   */
  protected void runExportSample() {
    if (m_biExport==null||!m_biExport.isVisible()) {
      this.setCursor(new Cursor(Cursor.WAIT_CURSOR));
      m_biExport = new BIExport(this, m_status);
      this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
    }
    m_biExport.setSize(700, 550);
    WindowUtils.centerWindow(m_biExport);
    m_biExport.setVisible(true);
  }

  /**
   * Run the linking sample
   */
  protected void runLinkingSample() {
    if (m_biLinking==null||!m_biLinking.isVisible()) {
      this.setCursor(new Cursor(Cursor.WAIT_CURSOR));
      m_biLinking = new BILinking(this, m_status);
      this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
    }
    m_biLinking.setSize(700, 550);
    WindowUtils.centerWindow(m_biLinking);
    m_biLinking.setVisible(true);
  }

  /**
   * Run the catalog sample
   */
  protected void runCatalogSample() {
    if (m_biCatalog==null||!m_biCatalog.isVisible()) {
      this.setCursor(new Cursor(Cursor.WAIT_CURSOR));
      m_biCatalog = new BICatalog(this, m_status);
      this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
    }
    m_biCatalog.setSize(700, 550);
    WindowUtils.centerWindow(m_biCatalog);
    m_biCatalog.setVisible(true);
  }

  /**
   * Run the metadata browser sample
   */
  protected void runMetadataSample() {
    if (m_biMetadata==null||!m_biMetadata.isVisible()) {
      this.setCursor(new Cursor(Cursor.WAIT_CURSOR));
      m_biMetadata = new BIMetadata(this, m_status);
      this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
    }
    m_biMetadata.setSize(700, 550);
    WindowUtils.centerWindow(m_biMetadata);
    m_biMetadata.setVisible(true);
  }

  /**
   * Run the graph sample
   */
  protected void runGraphSample() {
    if (m_biGraph==null||!m_biGraph.isVisible()) {
      this.setCursor(new Cursor(Cursor.WAIT_CURSOR));
      m_biGraph = new BIGraph(this, m_status);
      this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
    }
    m_biGraph.setSize(700, 550);
    WindowUtils.centerWindow(m_biGraph);
    m_biGraph.setVisible(true);
  }

  /**
   * Run the custom wizard sample
   */
  protected void runNewPresSample() {
    if (m_biNewPres==null||!m_biNewPres.isVisible()) {
      this.setCursor(new Cursor(Cursor.WAIT_CURSOR));
      m_biNewPres = new BINewPres(this, m_status);
      this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
    }
    m_biNewPres.setSize(700, 550);
    WindowUtils.centerWindow(m_biNewPres);
    m_biNewPres.setVisible(true);
  }

  /**
   * Run the print sample
   */
  protected void runPrintSample() {
    if (m_biPrint==null||!m_biPrint.isVisible()) {
      this.setCursor(new Cursor(Cursor.WAIT_CURSOR));
      m_biPrint = new BIPrint(this, m_status);
      this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
    }
    m_biPrint.setSize(700, 550);
    WindowUtils.centerWindow(m_biPrint);
    m_biPrint.setVisible(true);
  }
  
  /**
   * Run the dimlist sample
   */
  protected void runDimListSample() {
    if (m_biDimList==null||!m_biDimList.isVisible()) {
      this.setCursor(new Cursor(Cursor.WAIT_CURSOR));
      m_biDimList = new BIDimList(this, m_status);
      this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
    }
    m_biDimList.setSize(700, 550);
    WindowUtils.centerWindow(m_biDimList);
    m_biDimList.setVisible(true);
  }
  
  /**
   * Run the rules sample
   */
  protected void runRulesSample() {
    if (m_biRules==null||!m_biRules.isVisible()) {
      this.setCursor(new Cursor(Cursor.WAIT_CURSOR));
      m_biRules = new BIRules(this, m_status);
      this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
    }
    m_biRules.setSize(700, 550);
    WindowUtils.centerWindow(m_biRules);
    m_biRules.setVisible(true);
  }
  
  /**
   * Run the querybuilder sample
   */
  protected void runQuerybuilderSample() {
    if (m_biQuerybuilder==null||!m_biQuerybuilder.isVisible()) {
      this.setCursor(new Cursor(Cursor.WAIT_CURSOR));
      m_biQuerybuilder = new BIQuerybuilder(this, m_status);
      this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
    }
    m_biQuerybuilder.setSize(700, 550);
    WindowUtils.centerWindow(m_biQuerybuilder);
    m_biQuerybuilder.setVisible(true);
  }
    /**
     * Run the writeback sample
     */
    protected void runWritebackSample() {
        if (m_biWriteback == null || !m_biWriteback.isVisible()) {
            this.setCursor(new Cursor(Cursor.WAIT_CURSOR));
            m_biWriteback = new BIWriteback(this, m_status);
            this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
        }
        m_biWriteback.setSize(800, 600);
        WindowUtils.centerWindow(m_biWriteback);
        m_biWriteback.setVisible(true);
    }  

  /**
   * Retrieves the BISession instance created by this BIFrame.
   *
   * @return the BISession instance created by this BIFrame.
   */
  protected BISession getBISession() {
    return m_session;
  }

  /**
   * Retrieves the MetadataManager instance created by this BIFrame.
   *
   * @return the MetadataManager instance created by this BIFrame.
   */
  protected MetadataManager getMetadataManager() {
    return m_metadataManager;
  }

  /**
   * Retrieves the PersistenceManager instance created by this BIFrame.
   *
   * @return the PersistenceManager instance created by this BIFrame.
   */
  protected PersistenceManager getPersistenceManager() {
    return m_persistenceManager;
  }

  /**
   * Retrieves the QueryManager instance created by this BIFrame.
   *
   * @return the QueryManager instance created by this BIFrame.
   */
  protected QueryManager getQueryManager() {
    return m_queryManager;
  }

/**
   * Retrieves the status bar used by this BIFrame.  Subclasses should call
   * this method to retrieve and update the status bar information.
   *
   * @return the status bar used by this BIFrame.
   */
  protected JLabel getStatusBar() {
    return m_statusBar;
  }


  /**
   * Retrieves the main display panel for this BIFrame.  Subclasses should
   * use this panel for displaying views, for example.
   *
   * @return the main display panel for this BIFrame
   */
  protected JPanel getDisplayPanel() {
    return m_displayPanel;
  }

  /**
   * Creates and returns a default query.  The Query will be based on Sales
   * in the CS_OLAP Schema
   *
   * @return the default Query
   */
  protected Query getDefaultQuery () {
    String[] strMeasures = {"MDM!M_CS_OLAP.SHAWSALES.AMOUNT_SOLD"};
    m_query = m_queryManager.createQuery();   
    try {
      m_query.initCubeQuery(strMeasures, null);
    }
    catch (InvalidStepArgException isae) {
      showExceptionDialog(this, isae);
    }
    catch (MetadataManagerException mme) {
      showExceptionDialog(this, mme);
    }
    catch (QueryException qe) {
      showExceptionDialog(this, qe);
    }
    catch (SelectionException se) {
      showExceptionDialog(this, se);
    }

    return m_query;
  }

  /**
   * Initialize the user interface.
   * Subclasses should add custom initialization code here.
   */
  private void jbInit() throws Exception {
    // create the menu bar, the connect, disconnect and exit menu items
    JMenuBar menuBar = new JMenuBar();
    JMenu fileMenu = new JMenu("File");
    JMenuItem aboutMenu = new JMenuItem("About");
    JMenuItem exitMenu = new JMenuItem("Exit");
    
    final BIAboutDialog aboutDialog = new BIAboutDialog(this, "BI Beans About Dialog", true);
    aboutDialog.setSize(500,150);
    WindowUtils.centerWindow(aboutDialog);

    // set Mnemonic
    fileMenu.setMnemonic('F');
    exitMenu.setMnemonic('E');
    aboutMenu.setMnemonic('A');
    
    // add the file menu items
    fileMenu.add(aboutMenu);
    fileMenu.add(exitMenu);
    
    menuBar.add(fileMenu);
    
    // create a status bar
    m_statusBar = new JLabel("Status: Main Menu");
    
    // when the about item is selected, show the about dialog
    aboutMenu.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent event) {
        aboutDialog.setVisible(true);
      }
    });

    // when the exit item is selected, just close the frame and exit
    exitMenu.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent event) {
        exit();
      }
    });
    
    // create the main display panel
    if (m_displayPanel==null)
      m_displayPanel = new JPanel();
    else
      m_displayPanel.removeAll();
    m_displayPanel.setLayout(new BorderLayout());
    
    // put all of these into the frame
    setJMenuBar(menuBar);
    getContentPane().removeAll();
    getContentPane().add(m_displayPanel, BorderLayout.CENTER);
    getContentPane().add(m_statusBar, BorderLayout.SOUTH);

    // add a listener to listen for the window closing event
    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        exit();
      }
    });

    connect();
    populateHashtables();
    createLaunchPanel();
    
  }

   /**
   * Populates hashtable for the sample labels and descriptions
   *
   */
  protected void populateHashtables() {
  
    m_descriptions = new Hashtable();
    
    m_descriptions.put(m_mainLabel, "main.html");
    m_descriptions.put(m_queryMainLabel, "main.html");
    m_descriptions.put(m_presentationMainLabel, "main.html");
    m_descriptions.put(m_catalogMainLabel, "main.html");
    
    m_descriptions.put(m_calcLabel, "calc.html");
    m_descriptions.put(m_catalogLabel, "catalog.html");
    m_descriptions.put(m_dimListLabel, "dimList.html");
    m_descriptions.put(m_exportLabel, "export.html");
    m_descriptions.put(m_graphLabel, "graph.html");
    m_descriptions.put(m_linkingLabel, "linking.html");
    m_descriptions.put(m_metadataLabel, "metadata.html");
    m_descriptions.put(m_newPresLabel, "newPres.html");
    m_descriptions.put(m_printLabel, "print.html");
    m_descriptions.put(m_querybuilderLabel, "querybuilder.html");
    m_descriptions.put(m_rulesLabel, "rules.html");
    m_descriptions.put(m_writebackLabel, "writeback.html");
    
    

  }
  
  /**
   * Displays a launch pad for the samples
   *
   */
  protected void createLaunchPanel() {
      
      // Create a button for running the sample
      final JButton m_runButton = new JButton("Run this sample");
      
      // Create an empty tree
      DefaultMutableTreeNode top = new DefaultMutableTreeNode(m_mainLabel);
      DefaultMutableTreeNode query = new DefaultMutableTreeNode(m_queryMainLabel);
      DefaultMutableTreeNode presentation = new DefaultMutableTreeNode(m_presentationMainLabel);
      DefaultMutableTreeNode catalog = new DefaultMutableTreeNode(m_catalogMainLabel);
      DefaultMutableTreeNode sample = new DefaultMutableTreeNode(m_dimListLabel);
      query.add(sample);
       sample = new DefaultMutableTreeNode(m_querybuilderLabel);
      query.add(sample);
       sample = new DefaultMutableTreeNode(m_calcLabel);
      query.add(sample);
       sample = new DefaultMutableTreeNode(m_linkingLabel);
      query.add(sample);
       sample = new DefaultMutableTreeNode(m_writebackLabel);
      query.add(sample);
      top.add(query);
       sample = new DefaultMutableTreeNode(m_graphLabel);
      presentation.add(sample);
       sample = new DefaultMutableTreeNode(m_rulesLabel);
      presentation.add(sample);
       sample = new DefaultMutableTreeNode(m_newPresLabel);
      presentation.add(sample);
       sample = new DefaultMutableTreeNode(m_printLabel);
      presentation.add(sample);
      top.add(presentation);
       sample = new DefaultMutableTreeNode(m_catalogLabel);
      catalog.add(sample);
       sample = new DefaultMutableTreeNode(m_exportLabel);
      catalog.add(sample);
       sample = new DefaultMutableTreeNode(m_metadataLabel);
      catalog.add(sample);
      top.add(catalog);
      final JTree tree = new JTree(top);
      
      // Define editor pane for html description
      final JEditorPane m_editorPane = new JEditorPane();
            m_editorPane.setEditable(false);
      m_editorPane.addHyperlinkListener(new HyperlinkListener() {
        public void hyperlinkUpdate(HyperlinkEvent event) {
        if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
          try {
            m_editorPane.setPage(Thread.currentThread().getContextClassLoader().getResource(event.getDescription().toString()));
            // set the status for which sample to run
            if (event.getDescription().toString().equals("main.html"))
              m_status = m_mainLabel;
            else {
              int i = 0;
              for (Enumeration e = m_descriptions.keys(); e.hasMoreElements() ; i++) {
                //expand tree
                tree.expandRow(i);
                String temp = (String)e.nextElement();
                if (m_descriptions.get(temp).equals(event.getDescription().toString())) {
                  m_status = temp;
                }
              }
            }
            // disable the run button for the main description            
            m_runButton.setVisible(!m_status.equals(m_mainLabel));
            tree.setSelectionPath(tree.getNextMatch(m_status,0,Position.Bias.Forward)); 
          } 
          catch (Exception e) {
            System.err.print("Error: " + e);
          }
        }
        }
      });

      try {
      m_editorPane.setPage(Thread.currentThread().getContextClassLoader().getResource("main.html"));
      } 
      catch (Exception e) {
      showExceptionDialog(this, e);
      }
      
      JScrollPane editorScrollPane = new JScrollPane();
      editorScrollPane.getViewport().add( m_editorPane );
      editorScrollPane.setVerticalScrollBarPolicy(
                        JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
      editorScrollPane.setPreferredSize(new Dimension(550, 500));
      
      // Define the buttons pane
      JPanel buttonsPane = new JPanel();
      buttonsPane.add(m_runButton);
      m_runButton.setVisible(false);
      m_runButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent event) {
          if (m_status.equals(m_calcLabel))
            runCalcSample();
          else if (m_status.equals(m_exportLabel))
            runExportSample();
          else if (m_status.equals(m_linkingLabel))
            runLinkingSample();
          else if (m_status.equals(m_catalogLabel))
            runCatalogSample();
          else if (m_status.equals(m_metadataLabel))
            runMetadataSample();
          else if (m_status.equals(m_graphLabel))
            runGraphSample();
          else if (m_status.equals(m_newPresLabel))
            runNewPresSample();
          else if (m_status.equals(m_printLabel))
            runPrintSample();
          else if (m_status.equals(m_dimListLabel))
            runDimListSample();
          else if (m_status.equals(m_rulesLabel))
            runRulesSample();
            else if (m_status.equals(m_querybuilderLabel))
                runQuerybuilderSample();      
            else if (m_status.equals(m_writebackLabel))
                runWritebackSample();                  
        }
      });
      
      //Add tree listener
      tree.getSelectionModel().setSelectionMode
                (TreeSelectionModel.SINGLE_TREE_SELECTION);
      tree.addTreeSelectionListener(new TreeSelectionListener() {
        public void valueChanged(TreeSelectionEvent e) {
          DefaultMutableTreeNode node = (DefaultMutableTreeNode)
                                   tree.getLastSelectedPathComponent();
          // set the sample status to the focused sample
          m_status = node.getUserObject().toString();
                    
          // activate run button if on a sample
          m_runButton.setVisible(node.isLeaf());
          // load description
          try {
              m_editorPane.setPage(Thread.currentThread().getContextClassLoader().getResource(m_descriptions.get(m_status).toString()));    
            }
            catch (Exception ioex) {
              System.err.print("Error loading description: "+ioex);
          }            
          getDisplayPanel().revalidate();
          getDisplayPanel().repaint();
        }
      });

      //Create a scroll pane for the tree
      JScrollPane treeScrollPane = new JScrollPane();
      treeScrollPane.getViewport().add( tree );
      treeScrollPane.setPreferredSize(new Dimension(180, 500));
      
      //Create a split pane for the tree and description
      JSplitPane m_splitpane = new JSplitPane();
      m_splitpane.setOneTouchExpandable(true);
      m_splitpane.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
      m_splitpane.setRightComponent(editorScrollPane);    
      m_splitpane.setLeftComponent(treeScrollPane);
      m_splitpane.setDividerLocation(200);

      getDisplayPanel().add(m_splitpane, BorderLayout.NORTH);
      getDisplayPanel().add(buttonsPane, BorderLayout.SOUTH);
      getDisplayPanel().revalidate();
      getDisplayPanel().repaint();
    
  }
    
  /**
   * Displays an exception dialog for the error message where the parent
   * window is a dialog.
   *
   * @param the exception to display
   */
  protected void showExceptionDialog(Dialog dialog, Exception ex) {
    BIExceptionDialog exDlg = new BIExceptionDialog(dialog, ex, getTitle(),
                                ex.getMessage(), null);
    exDlg.display();
    exDlg.dispose();
  }

  /**
   * Displays an exception dialog for the error message where the parent
   * window is a frame.
   *
   * @param the exception to display
   */
  protected void showExceptionDialog(Frame frame, Exception ex) {
    BIExceptionDialog exDlg = new BIExceptionDialog(frame, ex, getTitle(),
                                ex.getMessage(), null);
    exDlg.display();
    exDlg.dispose();
  }

  /**
   * Handles the case when exit menu is selected or the user closes the window
   */
  protected void exit() {
    // disconnect before exiting
    disconnect();
    dispose();
    System.exit(0);
  }

  protected void init()
  {
  
    try
    {         
      jbInit();
    }
    catch(Exception e)
    {
    e.printStackTrace();
    }
    
    return;
  }

  
}