import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
import java.io.*;
import java.util.*;

/**
 * A basic extension of the javax.swing.JApplet class
 */
public class J2TablePrinterTestApplication extends JApplet
{
	public void init()
	{
		// This line prevents the "Swing: checked access to system event queue" message seen in some browsers.
		getRootPane().putClientProperty("defeatSystemEventQueueCheck", Boolean.TRUE);
		
		// This code is automatically generated by Visual Cafe when you add
		// components to the visual environment. It instantiates and initializes
		// the components. To modify the code, only use code syntax that matches
		// what Visual Cafe can generate, or Visual Cafe may be unable to back
		// parse your Java file into its visual environment.
		//{{INIT_CONTROLS
		getContentPane().setLayout(new BorderLayout(0,0));
		setSize(728,527);
		JPanel0.setDoubleBuffered(false);
		JPanel0.setLayout(new FlowLayout(FlowLayout.CENTER,5,5));
		getContentPane().add(BorderLayout.NORTH,JPanel0);
		JButton0.setText("New directory");
		JButton0.setActionCommand("Print");
		JPanel0.add(JButton0);
		JScrollPane1.setOpaque(true);
		getContentPane().add(BorderLayout.CENTER,JScrollPane1);
		JTable1.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF);
		JScrollPane1.getViewport().add(JTable1);
		JTable1.setFont(new Font("Dialog", Font.PLAIN, 11));
		JTable1.setBounds(0,0,0,0);
		JPanel1.setAlignmentY(0.0F);
		JPanel1.setLayout(new BoxLayout(JPanel1,BoxLayout.X_AXIS));
		getContentPane().add(BorderLayout.SOUTH, JPanel1);
		JButton1.setText("Print");
		JButton1.setActionCommand("Print");
		JPanel1.add(JButton1);
		JButton2.setText("Print Preview");
		JButton2.setActionCommand("Print");
		JPanel1.add(JButton2);
		JButton3.setText("Simple Page Setup");
		JButton3.setActionCommand("Print");
		JPanel1.add(JButton3);
		JButton4.setText("Detailed Page Setup");
		JButton4.setActionCommand("Print");
		JPanel1.add(JButton4);
		JLabelSpacer.setText("  ");
		JPanel1.add(JLabelSpacer);
		JPanel1.add(JLabel1);
		//}}
		
	    
	    //System.out.println(System.getProperty("java.version"));
	    JButton0.setFocusPainted(false);    // turn off "has focus" display
	    
	    JFileChooser chooser = new JFileChooser();
        directory = new File("C:\\");
	    chooser.setCurrentDirectory(directory);
	    chooser.setFileSelectionMode(chooser.DIRECTORIES_ONLY);
        chooser.setDialogTitle("Select a directory then Open");
        if (chooser.showOpenDialog(getParent())==JFileChooser.APPROVE_OPTION) directory = chooser.getSelectedFile(); 
        
		setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        attributes = readDirectory(directory);
        JTable1.setModel(new MyTableModel(attributes));
        adjustColumnWidths(JTable1);

        // locale tests (either of these lines work):
        //JTable1.setLocale(java.util.Locale.FRANCE);    // set locale for just this component
        //java.util.Locale.setDefault(java.util.Locale.FRANCE);  // set overall locale

        // variable row height test, uses new setRowHeight(int) method, only compiles and runs under JDK 1.3
        //java.util.Random rand = new java.util.Random();
        //for (int i=0; i<JTable1.getRowCount(); i++) {
        //    int height = 12 + (Math.abs(rand.nextInt()) % 32);    // uniformly distributed numbers on [12,43]
        //    JTable1.setRowHeight(i,height);
        //}
        
        // variable header height test
        //JTableHeader jth = JTable1.getTableHeader();
        //Dimension size = new Dimension(jth.getSize().width, 50);
        //jth.setPreferredSize(size);
        //JTable1.setTableHeader(jth);        
        
		repaint();
		setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
            
	    /* some useful code so you can detect clicking on different cells within the JTable
	    JTable1.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
	        public void valueChanged(ListSelectionEvent e) {
	            int colIndex = JTable1.getSelectedColumn();
	            int rowIndex = JTable1.getSelectedRow();
	            System.out.println("clicked on col, row: " + colIndex + " " + rowIndex);
	        }});
	    */
	    
	    j2tp = new com.wildcrest.j2tableprinter.J2TablePrinter();
		j2tp.addPropertyChangeListener(new PrintingStatusListener());
	    j2tp.setTable(JTable1);
	    
	    // test handling of intercell spacing and row margin values
	    //JTable1.setRowMargin(5);        // rowMargin automatically updates intercellSpacing.height
	    //Dimension ics = JTable1.getIntercellSpacing();
	    //ics.height = 10;
	    //ics.width = 10;
	    //JTable1.setIntercellSpacing(ics);
	    //j2tp.setPrintPreviewScale(2.0);     // useful to see print image magnified when debugging
	    
	    
	    // settings for HP OfficeJet 600
	    //j2tp.setUnprintableBottomMargin(.625);
	    //j2tp.setUnprintableTopMargin(.08);
	    //j2tp.setUnprintableLeftMargin(.25);
	    //j2tp.setUnprintableRightMargin(.25);
	    
	    
	    // test non-GUI (not displayed, data only) JTable:
	    //JTable table2 = new JTable();
	    //table2.setBounds(0,0,200,200);   // required
	    //table2.setModel(JTable1.getModel());
	    //j2tp.setTable(table2);
        
		    
        // Create a 2nd JTable with some data for optional Book test (column headers won't print since not in a JScrollPane)
        String[] columns = {"Company Name", "Symbol", "99 Rank", "97 Rank", "Revenues"};
        Object[][] data = {
            {"General Motors", "GM", "1", "1", "$161,315"},
            {"Ford Motor", "F", "2", "2", "$144,416"},
            {"Wal-Mart", "WMT", "3", "4", "$139,208"},
            {"ExxonMobil", "XOM", "4", "3", "$100,697"},
            {"General Electric", "GE", "5", "5", "$100,469"},
            {"IBM", "IBM", "6", "6", "$81,667"},
            {"Citigroup", "C", "7", "40", "$76,431"},
            {"Philip Morris", "MO", "8", "10", "$57,813"},
            {"Boeing", "BA", "9", "36", "$56,154"},
            {"AT&T", "T", "10", "7", "$53,588"}};

        table2 = new JTable(data, columns);     // this is non-GUI JTable...
        table2.setSize(500,250);                // .. and you must setSize else display and printing are blank
	        
        j2tp2 = new com.wildcrest.j2tableprinter.J2TablePrinter(); 
        j2tp2.setTable(table2);                 // load table2 into 2nd J2TablePrinter instance
        j2tp2.setOrientation(j2tp2.LANDSCAPE);  // test intermixing LANDSCAPE

	    // code for testing outside line drawing
	    //j2tp.setShowOutsideLines(false);  // test outside lines feature
	    //j2tp.setPrintArea(1,1,3,3);       // test print area feature
	    //j2tp2.setShowOutsideLines(false); // test outside lines feature
	    //j2tp2.setPrintArea(1,1,3,3);      // test print area feature
            
        // Book is a Pageable containing the pages from two J2TablePrinter instances, each of which are themselves Pageables
        // Create book and copy over all pages (as Printables) from each J2TablePrinter instance
        book = new java.awt.print.Book();
        for (int i=0; i<j2tp.getNumberOfPages(); i++)
            book.append(j2tp.getPrintable(i), j2tp.getPageFormat(i));
        for (int i=0; i<j2tp2.getNumberOfPages(); i++)
            book.append(j2tp2.getPrintable(i), j2tp2.getPageFormat(i));
        //System.out.println("j2tp1, j2tp2, book num pages: " 
        //    + j2tp.getNumberOfPages() + " " + j2tp2.getNumberOfPages() + " " + book.getNumberOfPages());
        // or, could change order or drop or duplicate pages if we want, e.g.:
        //book.append(j2tp2.getPrintable(2), j2tp2.getPageFormat(2));	    
        //book.append(j2tp2.getPrintable(0), j2tp2.getPageFormat(0));	
        //book.append(j2tp2.getPrintable(0), j2tp2.getPageFormat(0));	
            
    	    
		//{{REGISTER_LISTENERS
		SymAction lSymAction = new SymAction();
		JButton1.addActionListener(lSymAction);
		JButton2.addActionListener(lSymAction);
		JButton3.addActionListener(lSymAction);
		JButton4.addActionListener(lSymAction);
		JButton0.addActionListener(lSymAction);
		//}}
	}
		    
    
	class MyTableModel extends AbstractTableModel {
	    String[] columnNames = {"Name", "Length", "Last modified", "Is directory",
	        "Can read", "Can write", "Is hidden", "Path"};
	    Vector[] attributes;
	    MyTableModel(Vector[] attributes) { this.attributes = attributes; }
	    public int getColumnCount() { return columnNames.length; }
	    public int getRowCount() { return attributes[0].size(); }
	    public String getColumnName(int col) { return columnNames[col]; }
	    public Object getValueAt(int row, int col) { return attributes[col].elementAt(row); }
	    public Class getColumnClass(int col) { return getValueAt(0, col).getClass(); }
	    public boolean isCellEditable(int row, int col) { return true; }
	    public void setValueAt(Object value, int row, int col) {
	        attributes[col].setElementAt(value, row);
	        fireTableCellUpdated(row,col);
	    }
	}
	        
	Vector[] readDirectory(File directory) {
	    Vector[] attributes = new Vector[8];
        ImageIcon check = new ImageIcon("images/check.gif");
        ImageIcon ex = new ImageIcon("images/ex.gif");
        ImageIcon red = new ImageIcon("images/red-ball.gif");
        ImageIcon yellow = new ImageIcon("images/yellow-ball.gif");
        ImageIcon green = new ImageIcon("images/green-ball.gif");
        ImageIcon white = new ImageIcon("images/white-ball.gif");
	    
	    for (int i=0; i<8; i++) attributes[i] = new Vector();
        String path = directory.getPath();
        String[] contents = directory.list();
        for (int i=0; i<contents.length; i++) {
            String fullName = path + File.separator + contents[i];
            File f = new File(fullName);
            attributes[0].addElement(f.getName());
            attributes[1].addElement(new Long(f.length()));
            attributes[2].addElement(new Date(f.lastModified()).toString());  
            
            // simple text versions: 
            attributes[3].addElement(new Boolean(f.isDirectory()).toString());
            attributes[4].addElement(new Boolean(f.canRead()).toString());
            attributes[5].addElement(new Boolean(f.canWrite()).toString());
            attributes[6].addElement(new Boolean(f.isHidden()).toString());

            // boolean test (except JDK 1.2.2 has a bug printing JCheckBox in JTable)
            //attributes[3].addElement(new Boolean(f.isDirectory()));
            //attributes[4].addElement(new Boolean(f.canRead()));
            //attributes[5].addElement(new Boolean(f.canWrite()));
            //attributes[6].addElement(new Boolean(f.isHidden()));
            
            // fancy image versions (nice but 3-4X slower on JDK 1.2.2):
            //attributes[3].addElement( f.isDirectory() ? check : ex );
            //if (f.canRead()) attributes[4].addElement(green);
            //else             attributes[4].addElement(red);
            //if (f.canWrite()) attributes[5].addElement(green);
            //else             attributes[5].addElement(red);
            //if (f.isHidden()) attributes[6].addElement(yellow);
            //else              attributes[6].addElement(white);

            attributes[7].addElement(f.getPath());
        }
        return attributes;
    }
		
		
    void adjustColumnWidths(JTable table) {
        boolean stringCol[] = {true, false, true, false, false, false, false, true};
        int[] headerWidths = {33, 39, 77, 64, 51, 54, 51, 26};		// hard-coded header widths (yuck, see below)
        for (int i=0; i<table.getColumnCount(); i++) {
            TableColumn column = table.getColumnModel().getColumn(i);
            Component comp;
            String javaVersion = System.getProperty("java.version");
  
		    // incompatible change from JDK 1.2 to 1.3 (see Bug Parade 4276838)!!!  can only compile under JDK 1.3
		    //if (javaVersion.startsWith("1.2"))
		    // the next line works under 1.2 (won't run under 1.3)
		    //    comp = column.getHeaderRenderer()
		    //        .getTableCellRendererComponent(null, column.getHeaderValue(), false, false, 0, 0);
		    //else      
		    // the next line works only under JDK 1.3 (won't compile under 1.2)
		    //    comp = table.getTableHeader().getDefaultRenderer()
		    //        .getTableCellRendererComponent(null, column.getHeaderValue(), false, false, 0, 0);
		    //int headerWidth = comp.getPreferredSize().width+10;
		    //
		    // to provide sample code that will compile and run under both 1.2 and 1.3, we will hard-code values (yuck):
		    int headerWidth = headerWidths[i]+10;
		            
            TableModel model = table.getModel();
            Object longest;
            if (stringCol[i]) {
                String longestStr="";
                for (int j=0; j<model.getRowCount(); j++)
                    if (((String)(model.getValueAt(j,i))).length()>longestStr.length()) longestStr = (String)(model.getValueAt(j,i));
                longest = longestStr; 
            }
            else longest = model.getValueAt(0,i);
                
            comp = table.getDefaultRenderer(model.getColumnClass(i))
                .getTableCellRendererComponent(table, longest, false, false, 0, i);
            int cellWidth = comp.getPreferredSize().width;
            
            column.setPreferredWidth(Math.max(headerWidth, cellWidth));
        }
        return;
    }
    	

	//{{DECLARE_CONTROLS
	javax.swing.JPanel JPanel0 = new javax.swing.JPanel();
	javax.swing.JButton JButton0 = new javax.swing.JButton();
	javax.swing.JScrollPane JScrollPane1 = new javax.swing.JScrollPane();
	javax.swing.JTable JTable1 = new javax.swing.JTable();
	javax.swing.JPanel JPanel1 = new javax.swing.JPanel();
	javax.swing.JButton JButton1 = new javax.swing.JButton();
	javax.swing.JButton JButton2 = new javax.swing.JButton();
	javax.swing.JButton JButton3 = new javax.swing.JButton();
	javax.swing.JButton JButton4 = new javax.swing.JButton();
	javax.swing.JLabel JLabelSpacer = new javax.swing.JLabel();
	javax.swing.JLabel JLabel1 = new javax.swing.JLabel();
	//}}
	
	com.wildcrest.j2tableprinter.J2TablePrinter j2tp;
    com.wildcrest.j2tableprinter.J2TablePrinter j2tp2;
    JTable table2;
	java.awt.print.Book book;       // for optional Book test
	File directory;
	Vector[] attributes;
	
	
    // process events for: printing: true if done, false if busy
    //                     print dialog response: true if OK, false if cancel
    //                     page being printed: 1...n
	class PrintingStatusListener implements java.beans.PropertyChangeListener
	{
		public void propertyChange(java.beans.PropertyChangeEvent evt) {
		    if (evt.getPropertyName().equals("printing")) {
		        if (j2tp.isPrinting()) JLabel1.setText("About to print...");    // printing started
		        else                                                            // printing done
		            if (j2tp.isPrintDialogResponse())  {            // but only say so if didn't cancel
		                JLabel1.setText("Printing done");
		                try {Thread.currentThread().sleep(1000);}   // pause so can see
		                catch (Exception e) {}
		                JLabel1.setText("");
		            }
		    }
		    if (evt.getPropertyName().equals("printDialogResponse")) {
		        if (j2tp.isPrintDialogResponse()) JLabel1.setText("Start printing..."); // if said OK
		        else {                                                                  // if said cancel
		            JLabel1.setText("Printing canceled...");
		            try {Thread.currentThread().sleep(1000);}       // pause so can see
		            catch (Exception e) {}
		            }
		    }
		    if (evt.getPropertyName().equals("pageBeingPrinted")) {     // also get these events during printPreview, so...
		        if (j2tp.isPrinting() && j2tp.getPageBeingPrinted()>0)  // ...isPrinting() true means really printing
		            JLabel1.setText("Printing page " + j2tp.getPageBeingPrinted() + " of " + j2tp.getNumberOfPages());
		            // in preceding line, "of" should really be: Pageable-you-are-printing.getNumberOfPages()
		        else JLabel1.setText("");
		    }
		}
	}
	
	
	// main method so can run applet as an application
	static public void main(String args[]) {
		class DriverFrame extends JFrame {
			public DriverFrame() {
				addWindowListener(new java.awt.event.WindowAdapter() {
					public void windowClosing(java.awt.event.WindowEvent event) {
						dispose();	    // free the system resources
						System.exit(0); // close the application
					}
				});
				this.setTitle("J2TablePrinter Test Application");
				this.setSize(640,480);
                J2TablePrinterTestApplication applet = new J2TablePrinterTestApplication();
                applet.init();
				this.getContentPane().add(applet);
			}
		}
		new DriverFrame().show();
	}
	

	class SymAction implements java.awt.event.ActionListener
	{
		public void actionPerformed(java.awt.event.ActionEvent event)
		{
			Object object = event.getSource();
			if (object == JButton1)
				JButton1_actionPerformed(event);
			else if (object == JButton2)
				JButton2_actionPerformed(event);
			else if (object == JButton3)
				JButton3_actionPerformed(event);
			else if (object == JButton4)
				JButton4_actionPerformed(event);
			else if (object == JButton0)
				JButton0_actionPerformed(event);
		}
	}

	void JButton1_actionPerformed(java.awt.event.ActionEvent event)
	{
		// to do: code goes here.
	    // various print tests, all of these work:
	    j2tp.print();             // normal useage test: print j2tp's own JTable
		//j2tp.print(JTable1);      // J2TablePrinter1 prints its own JTable1
	    //j2tp.print(j2tp);         // print self as Pageable
		//j2tp.print(table2);       // J2TablePrinter1 prints J2TablePrinter2's JTable rather than its own
		//j2tp.print(j2tp2);        // print J2TablePrinter2 as a Pageable using J2TablePrinter1
		//j2tp.print(book);         // Book test: book = J2TablePrinter1 + J2TablePrinter2, printed by J2TablePrinter1
	}

	void JButton2_actionPerformed(java.awt.event.ActionEvent event)
	{
		// to do: code goes here.
		// test custom print preview page setup dialog:
	    J2TablePrinterPageSetupDialog J2TablePrinterPageSetupDialog1 = new J2TablePrinterPageSetupDialog(j2tp);
		J2TablePrinterPageSetupDialog1.setModal(true);
		J2TablePrinterPageSetupDialog1.setTitle("Page Setup");
		j2tp.setPrintPreviewPageSetupDialog(J2TablePrinterPageSetupDialog1);
		
		// test omitting Page Setup button from Print Preview dialog:
		//J2TextPrinter1.showPrintPreviewPageSetupButton(false);
	
		// NOTE: "this" = Component from which dialog is displayed, so dialog is brought to front along with JApplet
		// various print preview tests, all of these work:
		j2tp.showPrintPreviewDialog(this);          // normal useage test: preview j2tp's own JTable
        //j2tp.showPrintPreviewDialog(this,j2tp);      // J2TablePrinter1 previews itself as Pageable
        //j2tp.showPrintPreviewDialog(this,j2tp2);     // J2TablePrinter1 previews J2TablePrinter2 as Pageable
        //j2tp.showPrintPreviewDialog(this,book);      // Book test: book = J2TablePrinter1 + J2TablePrinter2, printed by J2TablePrinter1
	}

	void JButton3_actionPerformed(java.awt.event.ActionEvent event)
	{
		// to do: code goes here.
		// Simple (system) Page Setup:
		j2tp.showPageSetupDialog();
	}

	void JButton4_actionPerformed(java.awt.event.ActionEvent event)
	{
		// to do: code goes here.
		// Detailed Page Setup:
		J2TablePrinterPageSetupDialog J2TablePrinterPageSetupDialog1 = new J2TablePrinterPageSetupDialog(j2tp);
		J2TablePrinterPageSetupDialog1.setModal(true);
		J2TablePrinterPageSetupDialog1.setTitle("Page Setup");
		J2TablePrinterPageSetupDialog1.show();
			 
	}

	void JButton0_actionPerformed(java.awt.event.ActionEvent event)
	{
		// to do: code goes here.
		// New directory:
	    JFileChooser chooser = new JFileChooser();
	    if (directory.getParent()==null) chooser.setCurrentDirectory(directory);
	    else chooser.setCurrentDirectory(new File(directory.getParent()));
	    
	    chooser.setFileSelectionMode(chooser.DIRECTORIES_ONLY);
        chooser.setDialogTitle("Select a directory then Open");
        if (chooser.showOpenDialog(getParent())!=JFileChooser.APPROVE_OPTION) return;
        
        File newDir = chooser.getSelectedFile();
        if (newDir.equals(directory)) return;
        directory = newDir;
		
		setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        attributes = readDirectory(directory);
        TableModel tableModel = new MyTableModel(attributes);
        JTable1.setModel(tableModel);
        adjustColumnWidths(JTable1);
        repaint();
		setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
	}
}
