import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
//import javax.swing.border.*;
import javax.swing.table.*;
import java.io.*;
import java.util.*;

/** DemoTable 3 - similar to <code>DemoTable2</code> except adding buttons
* to change the look and feel.<p>
*
* Example invocation:<p>
*
* <pre>
*     java DemoTable3 worldrecordswomen.txt -d, -h
* </pre>
*
* Screen snap showing Motif L&F...<br>
* <center><img src="DemoTable3-1.gif"></center><p>
*
* Screen snap showing Windows L&F...<br>
* <center><img src="DemoTable3-2.gif"></center><p>
*
* Screen snap showing Java (Metal)...<br>
* <center><img src="DemoTable3-3.gif"></center><p>
*
* @see <a href="DemoTable3.java">source code</a>
* @author Scott MacKenzie, 2002
*/
public class DemoTable3
{
   public static void main(String[] args)
   {
      // 1-3 command-line args required

      if (args.length < 1 || args.length > 3)
      {
         System.out.println(
            "usage: java DemoTable3 file [-dc] [-h]\n\n" +
            "where file  = file containing data to place in table\n" +
            "      [-dc] = use delimiter character(s) c for row entries\n" +
            "      [-h]  = first line in file contains column header names"
         );
         System.exit(0);
      }

      // get command-line arguments

      String fileName = args[0];

      boolean headerOption = false;
      String delimiterString = " \t\n\r\f"; // default for StringTokenizer

      for (int i = 1; i < args.length; ++i)
      {
         if (args[i].indexOf("-d") == 0 && args[i].length() > 2)
            delimiterString = args[i].substring(2);

         if (args[i].equals("-h"))
            headerOption = true;
      }

      // prepare to read data file

      BufferedReader br = null;
      try
      {
         br = new BufferedReader(new FileReader(fileName));
      } catch (FileNotFoundException e)
      {
         System.out.println("File not found: " + fileName);
         System.exit(1);
      }

      StringTokenizer st;
      String line = null;
      int first = 0;
      int n = 0;

      // verify that each row contains the same number of elements

      while (true)
      {
         try
         {
            line = br.readLine();
         }
         catch (IOException e)
         {
            System.out.println("Error reading data file");
            System.exit(1);
         }
         if (line == null) break;

         st = new StringTokenizer(line, delimiterString);
         n = st.countTokens();
         if (first == 0) first = n;
         if (n != first)
         {
            System.out.println("Data format error!");
            System.exit(1);
         }
      }

      // close file

      try
      {
         br.close();
      } catch (IOException e) {}

      // re-open file

      try
      {
         br = new BufferedReader(new FileReader(fileName));
      } catch (FileNotFoundException e) {}

      // read the column names into a Vector (if -h option)

      Vector columnNames = new Vector();
      if (headerOption)
      {
         try
         {
            line = br.readLine();
         }
         catch (IOException e)
         {
            System.out.println("Error reading data file");
            System.exit(1);
         }
         if (line == null) return;

         st = new StringTokenizer(line, delimiterString);
         while (st.hasMoreTokens())
            columnNames.add(st.nextToken());
      }

      // read the row data into a Vector of Vectors

      Vector rowData = new Vector();
      Vector tmp;
      while (true)
      {
         try
         {
            line = br.readLine();
         }
         catch (IOException e)
         {
            System.out.println("Error reading data file");
            System.exit(1);
         }
         if (line == null) break;

         tmp = new Vector();
         st = new StringTokenizer(line, delimiterString);
         while (st.hasMoreTokens())
            tmp.add(st.nextToken());
         rowData.add(tmp);
      }

      // use generic column names, if necessary

      if (!headerOption)
      {
         for (int i = 0; i < n; ++i)
            columnNames.add("" + (char)('A' + i));
      }

      // OK, we're ready to build the GUI with the data in a JTable

      DemoTable3Frame frame = new DemoTable3Frame(rowData, columnNames);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setTitle("DemoTable3");
      frame.pack();
      frame.show();
   }
}

class DemoTable3Frame extends JFrame implements ActionListener
{
   private JButton[] lafButton;
   private JTextField statusField;
   private UIManager.LookAndFeelInfo[] laf;

   public DemoTable3Frame(Vector rowData, Vector columnNames)
   {
      // -------------------------------
      // create and configure components
      // -------------------------------

      laf = UIManager.getInstalledLookAndFeels();

      try {
         UIManager.setLookAndFeel(laf[0].getClassName());
      } catch (Exception e)
      {
         System.out.println(e);
      }

      statusField = new JTextField(10);
      statusField.setEditable(false);
      statusField.setMargin(new Insets(0, 3, 0, 0));
      statusField.setText(laf[0].getName());

      lafButton = new JButton[laf.length];
      for (int i = 0; i < lafButton.length; ++i)
      {
         lafButton[i] = new JButton(laf[i].getName());
         lafButton[i].setActionCommand("" + i);
         lafButton[i].addActionListener(this);
      }

      // construct a table data model, passing the data as arguments

      CustomTableModel dataModel = new CustomTableModel(rowData, columnNames);

      // construct a table, passing the data model as an argument

      JTable t = new JTable(dataModel);

      JScrollPane sp = new JScrollPane(t);
      sp.setPreferredSize(new Dimension(600, 200));

      // ------------------
      // arrange components
      // ------------------

      // put components in panels

      JPanel p2 = new JPanel();
      p2.add(new JLabel("<html><font size=+1 face=sanserif>" +
         "Select Desired Look and Feel"));
      p2.setMaximumSize(p2.getPreferredSize());

      JPanel p3 = new JPanel();
      for (int i = 0; i < lafButton.length; ++i)
         p3.add(lafButton[i]);
      p3.setMaximumSize(p3.getPreferredSize());

      JPanel p4 = new JPanel();
      p4.add(new JLabel("Current L&F: "));
      p4.add(statusField);
      p4.setMaximumSize(p4.getPreferredSize());

      JPanel panel = new JPanel();
      panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
      panel.add(sp);
      panel.add(Box.createRigidArea(new Dimension(0, 20)));
      panel.add(p2);
      panel.add(p3);
      panel.add(p4);
      panel.add(Box.createVerticalGlue());

      // make panel this JFrame's content pane

      this.setContentPane(panel);
   }

   // -------------------------------
   // implement ActionListener method
   // -------------------------------

   public void actionPerformed(ActionEvent ae)
   {
      JButton b = (JButton)ae.getSource();
      statusField.setText(b.getText());
      int idx = Integer.parseInt(b.getActionCommand());
      try
      {
         UIManager.setLookAndFeel(laf[idx].getClassName());
      } catch (Exception e)
      {
         System.out.println(e);
      }
      statusField.setText(laf[idx].getName());
      SwingUtilities.updateComponentTreeUI(this);
   }

   // -----------
   // inner class
   // -----------

   class CustomTableModel extends AbstractTableModel
   {
      Vector rowData, columnNames;

      public CustomTableModel(Vector rowData, Vector columnNames)
      {
         this.rowData = rowData;
         this.columnNames = columnNames;
      }

      public int getColumnCount()
      {
         return columnNames.size();
      }

      public int getRowCount()
      {
         return rowData.size();
      }

      public boolean isCellEditable(int row, int col)
      {
         return true;
      }

      public String getColumnName(int idx)
      {
         return (String)columnNames.elementAt(idx);
      }

      public Object getValueAt(int row, int col)
      {
         return ((Vector)rowData.elementAt(row)).elementAt(col);
      }

      public void setValueAt(Object value, int row, int col)
      {
         ((Vector)rowData.elementAt(row)).setElementAt(value, col);
         fireTableCellUpdated(row, col);
      }
   }
}


