/*
 * Copyright (c) 1997, 1998 Subrahmanyam Allamaraju. All Rights Reserved.
 * 
 * Permission to use, copy, modify, and distribute this software for
 * NON-COMMERCIAL purposes and without fee is hereby granted provided that this
 * copyright notice appears in all copies.
 *
 * This software is intended for demonstration purposes only, and comes without
 * any explicit or implicit warranty.
 *
 * Send all queries about this product to sallamar@cvimail.cv.com
 *
 */


import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;

/**
 * Import the package that contains the Table widget.
 */
import COM.Subrahmanyam.table.*;


public class TableFrame extends Frame implements ActionListener, ItemListener
{
    // The UI components.
    Button addRow, addColumn;
    Button deleteRow, deleteColumn;
    LabledTextField rowAt, columnAt;
    Checkbox showHSep, showVSep;
    Checkbox allowMultipleSelections;
    Checkbox hilite1, hilite2, hilite3;
    CheckboxGroup hiliteGroup;
    Button clear, clearAll;
    Checkbox singleClick, doubleClick;
    CheckboxGroup selMode;
    Choice normalFG, normalBG, reverseFG, reverseBG;
    //Choice fontChoice1, fontChoice2;
    Button headerFont, dataFont;
    Font f1, f2;
    
    // The Table widget.
    Table table;

    // The status bar.
    TextField status;

    // To circulate through the titles and data arrays.
    private int titleInd = -1;
    private int dataInd = -1;

    // Titiles for the Table header.
    String titles[] = {new String("One"), new String("Two"), 
		       new String("Three"), new String("Cheers"), 
		       new String("Four"), new String("Five"),  
		       new String("Six"), new String("Seven"),
		       new String("Eight"), new String("Nine"), 
		       new String("Ten"), new String("That's"), 
		       new String("all"), new String("fellows")};
    
    // Data strings for the Table data.
    String data[] = {new String("Hello"), new String("This"), 
		     new String("is"), new String("wonderful!"), 
		     new String("Oh! Ya!"), new String("How"), 
		     new String("do"), new String("you do?"), 
		     new String("Done"), new String("Quit"), 
		     new String("Winner"), new String("never"), 
		     new String("sleeps."), new String("Java"), 
		     new String("is"), new String("not just another"), 
		     new String("language."), new String("I'm fine"),
		     new String("Are you OK!"), new String("Ya. That's all!"), 
		     new String("Hello"), new String("This"), 
		     new String("is"), new String("wonderful!"), 
		     new String("Oh! Ya!"), new String("How"), 
		     new String("do"), new String("you do?"),
		     new String("Done"), new String("Quit"), 
		     new String("Winner"), new String("never"), 
		     new String("sleeps."), new String("Java"), 
		     new String("is"), new String("not just another"), 
		     new String("language."), new String("I'm fine"),
		     new String("Are you OK!"), new String("Ya. That's all!")}; 
    
    // Some colors.
    Color colorObjects[] = {Color.black, Color.blue, Color.cyan,
				    Color.darkGray, Color.gray, Color.lightGray,
				    Color.magenta, Color.orange, Color.pink,
				    Color.red, Color.white, Color.yellow};

    // Color strings.
    String colors[] = {new String("black"), new String("blue"), new
		       String("cyan"), new String("darkGray"), new
		       String("gray"), new String("lightGray"), new
		       String("magenta"), new String("orange"), new
		       String("pink"), new String("red"), new
		       String("white"), new String("yellow")  };
	    
    /**
     * Constructor for the Demo frame.
     */
    public TableFrame(Applet parent, String title) 
	{
	    super(title);

	    // Initialize some panels and the UI components.
	    FramedPanel panel1 = new FramedPanel();
	    
	    addRow = new Button("Add");
	    addColumn = new Button("Add");
	    deleteRow = new Button("Delete");
	    deleteColumn = new Button("Delete");
	    rowAt = new LabledTextField("Row", "0");
	    columnAt = new LabledTextField("Column", "0");
	    
	    addRow.addActionListener(this);
	    addColumn.addActionListener(this);
	    deleteRow.addActionListener(this);
	    deleteColumn.addActionListener(this);
	    rowAt.addActionListener(this);
	    columnAt.addActionListener(this);
	    
	    panel1.setLayout(new GridLayout(0, 3));
	    
	    panel1.add(columnAt);
	    panel1.add(addColumn);
	    panel1.add(deleteColumn);

	    panel1.add(rowAt);
	    panel1.add(addRow);
	    panel1.add(deleteRow);

	    FramedPanel panel2 = new FramedPanel();
	    
	    panel2.setLayout(new GridLayout(3, 1));
	    
	    panel2.add(new Label("Separators"));

	    showHSep = new Checkbox("Row");
	    showVSep = new Checkbox("Column");
	    allowMultipleSelections = new Checkbox("Multiple selections");
	    
	    showHSep.addItemListener(this);
	    showVSep.addItemListener(this);
	    allowMultipleSelections.addItemListener(this);
	    
	    panel2.add(showHSep);
	    panel2.add(showVSep);
	    
	    FramedPanel panel3 = new FramedPanel();
	    panel3.setLayout(new GridLayout(4, 1, 2, 2));
	    
	    selMode = new CheckboxGroup();
	    singleClick = new Checkbox("Single-click", selMode, false);
	    doubleClick = new Checkbox("Double-click", selMode, true);

	    singleClick.addItemListener(this);
	    doubleClick.addItemListener(this);
	    allowMultipleSelections.addItemListener(this);
	    panel3.add(new Label("Selection"));
	    panel3.add(singleClick);
	    panel3.add(doubleClick);
	    panel3.add(allowMultipleSelections);

	    FramedPanel panel4 = new FramedPanel();
	    panel4.setLayout(new GridLayout(4, 1, 2, 2));
	    
	    hiliteGroup = new CheckboxGroup();
	    hilite1 = new Checkbox("Element", hiliteGroup, false);
	    hilite2 = new Checkbox("Row", hiliteGroup, true);
	    hilite3 = new Checkbox("Column", hiliteGroup, false);
	    
	    hilite1.addItemListener(this);
	    hilite2.addItemListener(this);
	    hilite3.addItemListener(this);

	    panel4.add(new Label("Hilite"));
	    
	    panel4.add(hilite1);
	    panel4.add(hilite2);
	    panel4.add(hilite3);
	    
	    clear = new Button("Clear the contents");
	    clearAll = new Button("Clear the table");
	    
	    clear.addActionListener(this);
	    clearAll.addActionListener(this);
	    
	    // Construct the Table and set some attributes.
	    table = new Table();
	    table.setSize(700, 300);
	    
	    table.showHorizontalSeparator(false);
	    table.showVerticalSeparator(false);
	    table.setHiliteMode(Table.HILITE_ROW);
	    table.setClickMode(Table.DOUBLE_CLICK);
	    table.setLineSpacing(1.5);

	    table.addActionListener(this);
	    table.addItemListener(this);
	    
	    status = new TextField("Welcome to the demo!");
	    status.setEditable(false);
	    
	    // Set the layout and add the components.
	    GridBagLayout gridBag = new GridBagLayout();
	    GridBagConstraints c = new GridBagConstraints();
	    
	    setLayout(gridBag);

	    c.fill = GridBagConstraints.VERTICAL;
	    c.weightx = 0;
	    c.weighty = 0;
	   
	    int row = 0;

	    FramedPanel panel0 = new FramedPanel();
	    panel0.setLayout(new GridLayout(1, 1));
	    c.fill = GridBagConstraints.HORIZONTAL;
	    
	    panel0.add(new Label("Table Demo", Label.CENTER));
	    addComponent(panel0, gridBag, c, row, 0, 5, 1);
	    
	    c.anchor = GridBagConstraints.NORTHWEST;
	    c.fill = GridBagConstraints.BOTH;
	    
	    row++;
	    
	    addComponent(panel1, gridBag, c, row, 0, 2, 1);
	    
	    addComponent(panel3, gridBag, c, row, 2, 1, 1);
	    
	    addComponent(panel4, gridBag, c, row, 3, 1, 1);

	    addComponent(panel2, gridBag, c, row, 4, 1, 1);
	    
	    row++;
	    
	    FramedPanel panel5 = new FramedPanel();
	    panel5.setLayout(new GridLayout(0, 1));
	    
	    panel5.add(clear);
	    panel5.add(clearAll);
	    addComponent(panel5, gridBag, c, row, 0, 1, 1);

	    
	    
	    normalFG = new Choice();
	    reverseFG = new Choice();
	    normalBG = new Choice();
	    reverseBG = new Choice();
	    
	    normalFG.addItemListener(this);
	    normalBG.addItemListener(this);
	    reverseFG.addItemListener(this);
	    reverseBG.addItemListener(this);
	    
	    for(int i = 0; i < colors.length; i++) {
		normalFG.addItem(colors[i]);
		reverseFG.addItem(colors[i]);
		normalBG.addItem(colors[i]);
		reverseBG.addItem(colors[i]);
	    }
	    
	    normalFG.select("black");
	    normalBG.select("white");
	    reverseFG.select("white");
	    reverseBG.select("black");
	    
	    FramedPanel panel6 = new FramedPanel();
	    panel6.setLayout(new GridLayout(2, 0));
	    
	    panel6.add(new Label("Normal FG"));
	    panel6.add(normalFG);
	    panel6.add(new Label("Normal BG"));
	    panel6.add(normalBG);
	    
	    panel6.add(new Label("Reverse FG"));
	    panel6.add(reverseFG);
	    panel6.add(new Label("Reverse BG"));
	    panel6.add(reverseBG);
	    
	    addComponent(panel6, gridBag, c, row, 1, 2, 1);

	    headerFont = new Button("Change");
	    dataFont = new Button("Change");
	    headerFont.addActionListener(this);
	    dataFont.addActionListener(this);
	    
	    f1 = new Font("Helvetica", Font.BOLD, 15);
	    f2 = new Font("Helvetica", Font.PLAIN, 12);
	    
	    table.setFonts(f1, f2);
	    
	    FramedPanel panel7 = new FramedPanel();
	    panel7.setLayout(new GridLayout(2, 0));
	    
	    panel7.add(new Label("Header font"));
	    panel7.add(headerFont);
	    panel7.add(new Label("Data font"));
	    panel7.add(dataFont);

	    addComponent(panel7, gridBag, c, row, 3, 2, 1);
	    
	    row++;
	    
	    c.weightx = 1000; 
	    c.weighty = 10; 
	    c.fill = GridBagConstraints.BOTH;
	    addComponent(table, gridBag, c, row, 0, 5, 1);

	    row++;
	    
	    c.weightx = 0;
	    c.weighty = 0;
	    c.fill = GridBagConstraints.HORIZONTAL;
	    addComponent(status, gridBag, c, row, 0, 5, 1);
	    

	    setColors();
	    
	    validate();

	}
    
 
    public void actionPerformed(ActionEvent ae) 
	{
	    Object target = ae.getSource();
	    
	    if(target == rowAt) {
		try {
		    int row = Integer.parseInt(rowAt.getText());
		    if(row < table.getNoRows()) {
			table.selectRow(row);
			status.setText("Row " + row + " selected.");
		    }
		}
		catch(NumberFormatException ex) {
		    status.setText("Invalid row number.");
		}
	    }
	    else if(target == columnAt) {
		try {
		    int col = Integer.parseInt(columnAt.getText());
		    if(col < table.getNoColumns()) {
			table.selectColumn(col);
			status.setText("Column " + col + " selected.");
		    }
		}
		catch(NumberFormatException ex) {
		    status.setText("Invalid column number.");
		}
	    }
	    else if(target == addRow) {
		if(table.getNoColumns() > 0) {

		    String s[];
		    s = new String[table.getNoColumns()];
		    for(int i = 0; i < table.getNoColumns(); i++) {
			dataInd++;
			if(dataInd > data.length - 1) dataInd = 0;
			s[i] = data[dataInd];
		    }
		
		    try {
			int row = Integer.parseInt(rowAt.getText());
			
			table.addRow(row, s);
			table.repaint();
			status.setText("Rows: " + table.getNoRows() + 
				       ", Columns: " + table.getNoColumns());
		    }
		    catch(NumberFormatException ex) {
			status.setText("Invalid row number.");
		    }
		}
	    }
	    else if(target == addColumn) {
		String s[];
		int c = 1;
		if(c < table.getNoRows()) c = table.getNoRows();
		s = new String[c];
		for(int i = 0; i < c; i++) {
		    dataInd++;
		    if(dataInd > data.length - 1) dataInd = 0;
		    s[i] = data[dataInd];
		}
		
		++titleInd;
		if(titleInd >= titles.length) titleInd = 0;
		
		try {
		    int col = Integer.parseInt(columnAt.getText());
		    
		    table.addColumn(col, titles[titleInd], s);
		    
		    table.repaint();
		    status.setText("Rows: " + table.getNoRows() + 
				   ", Columns: " + table.getNoColumns());
		}
		catch(NumberFormatException ex) {
		    status.setText("Invalid column number.");
		}
	    }
	    else if(target == deleteRow) {
		try {
		    int row = Integer.parseInt(rowAt.getText());
		    String s[];
		    s = table.deleteRow(row);
		    if(s != null) {
			StringBuffer sb = new StringBuffer("Deleted Row: ");
			for(int i = 0; i < s.length; i++)
			    sb.append(s[i] + " ");
			status.setText(sb.toString());
		    }
		}
		catch(NumberFormatException ex) {
		    status.setText("Invalid row number.");
		}
	    }
	    else if(target == deleteColumn) {
		try {
		    int col = Integer.parseInt(columnAt.getText());
		    String s[];
		    s = table.deleteColumn(col);
		    if(s != null) {
			StringBuffer sb = new StringBuffer("Deleted Column: ");
			for(int i = 0; i < s.length; i++)
			    sb.append(s[i] + " ");
			status.setText(sb.toString());
		    }
		}
		catch(NumberFormatException ex) {
		    status.setText("Invalid column number.");
		}
	    }
	    else if(target == clear) {
		table.clear();
		status.setText("Rows: " + table.getNoRows() + ", Columns: "
				   + table.getNoColumns());
	    }
	    else if(target == clearAll) {
		table.clearAll();
		status.setText("Rows: " + table.getNoRows() + ", Columns: "
				   + table.getNoColumns());
	    }
	    else if(target == table) {
		status.setText("Action event: Row: " + table.getSelRowIndex() + 
			       ", Column: " + table.getSelColumnIndex());
	    }
	    else if(target == headerFont) {
		FontChooser fc = new FontChooser(this, f1);
		fc.setSize(450, 250);
		fc.setVisible(true);
		if(fc.isOk()) f1 = fc.getChoiceFont();
		fc.dispose();
		table.setFonts(f1, f2);
	    }
	    else if(target == dataFont) {
		FontChooser fc = new FontChooser(this, f2);
		fc.setSize(300, 200);
		fc.setVisible(true);
		if(fc.isOk()) f2 = fc.getChoiceFont();
		fc.dispose();
		table.setFonts(f1, f2);
	    }
	}
    
    public void itemStateChanged(ItemEvent ie) 
	{
	    Object target = ie.getSource();
	    if(target == showHSep) {
		if(showHSep.getState()) table.showHorizontalSeparator(true);
		else table.showHorizontalSeparator(false);
		table.repaint();
		status.setText("Horizontal separator toggled.");
	    }
	    else if(target == showVSep) {
		if(showVSep.getState()) table.showVerticalSeparator(true);
		else table.showVerticalSeparator(false);
		table.repaint();
		status.setText("Vertical separator toggled.");
	    }
	    else if(target == allowMultipleSelections) {
		if(allowMultipleSelections.getState())
		    table.allowMultipleSelections(true);
		else
		    table.allowMultipleSelections(false);
		status.setText("Multilple selections: " +
			       allowMultipleSelections.getState());
	    }
	    else if(target == hilite1) {
		table.setHiliteMode(Table.HILITE_ELEMENT);
		status.setText("Dynamic element selection set.");
	    }
	    else if(target == hilite2) {
		table.setHiliteMode(Table.HILITE_ROW);
		status.setText("Dynamic row selection set.");
	    }
	    else if(target == hilite3) {
		table.setHiliteMode(Table.HILITE_COLUMN);
		status.setText("Dynamic column selection set.");
	    }
	    else if(target == singleClick) {
		table.setClickMode(Table.SINGLE_CLICK);
		status.setText("Selection via single-click.");
		allowMultipleSelections.setEnabled(false);
	    }
	    else if(target == doubleClick) {
		table.setClickMode(Table.DOUBLE_CLICK);
		status.setText("Selection via double-click.");
		allowMultipleSelections.setEnabled(true);
	    }
	    else if(target == table) {
		if(ie.getStateChange() == ItemEvent.SELECTED) {
		    TElement s[];
		    s = table.getSelection();
		    if(s != null) {
			StringBuffer sb = new StringBuffer("Selection: ");
			for(int i = 0; i < s.length; i++) 
			    sb.append("[ "+ s[i].getRow() + ", " + s[i].getColumn()
				      + "] "); 
			status.setText(sb.toString());
		    }
		}
		else if(ie.getStateChange() == ItemEvent.DESELECTED) {
		    TElement s[];
		    s = table.getSelection();
		    if(s != null) {
			StringBuffer sb = new StringBuffer("DeSelection: ");
			for(int i = 0; i < s.length; i++) 
			    sb.append("[ "+ s[i].getRow() + ", " + s[i].getColumn()
				      + "] "); 
			status.setText(sb.toString());
		    }
		}
	    }
	    else if(target == normalFG || target == normalBG || target ==
		    reverseFG || target == reverseBG) {
		setColors();
	    }
	}
    

    /*
     * To set the colors.
     */
    private void setColors() 
	{
	    try {
		int nFG = normalFG.getSelectedIndex();
		int nBG = normalBG.getSelectedIndex();
		int rFG = reverseFG.getSelectedIndex();
		int rBG = reverseBG.getSelectedIndex();
		
		int row = Integer.parseInt(rowAt.getText());
		int col = Integer.parseInt(columnAt.getText());
		
		table.setColors(Color.black, new Color(168, 168, 168), colorObjects[nFG],
				colorObjects[nBG], colorObjects[rFG],
				colorObjects[rBG]);  
	    }
	    catch(NumberFormatException ex) {
		status.setText("Invalid row or column number.");
	    }	    
	}
    
    
    /*
     * To add components with the GridBagLayout.
     */
    private void addComponent(Component c, GridBagLayout g, GridBagConstraints
			      gc, int row, int column, int width, int height) 
	{
	    gc.gridx = column;
	    gc.gridy = row;
	    
	    gc.gridwidth = width;
	    gc.gridheight = height;
	    
	    g.setConstraints(c, gc);
	    add(c);
	}

}

/*
 * A Panel with the 3D border.
 */
class FramedPanel extends Panel {
    
    public Insets getInsets() {
        return new Insets(4,4,5,5);
    }

    public void paint(Graphics g) {
        Dimension d = getSize();
        Color bg = getBackground();
 
        g.setColor(bg);
        g.draw3DRect(0, 0, d.width - 1, d.height - 1, false);
        g.draw3DRect(3, 3, d.width - 7, d.height - 7, true);
    }
}



class LabledTextField extends Panel implements ActionListener
{
    Label l;
    TextField tf;
    Vector als;
    
    public LabledTextField(String label, String field) 
	{
	    super();
	    l = new Label(label, Label.LEFT);
	    tf = new TextField(field, 3);
	    tf.addActionListener(this);
	    add(l);
	    add(tf);	    

	    als = new Vector();
	}

    public void actionPerformed(ActionEvent e) 
	{
	    ActionEvent a = new ActionEvent(this, ActionEvent.ACTION_PERFORMED,
					    e.getActionCommand()); 
	    
	    for(int i = 0; i < als.size(); i++) 
		((ActionListener) als.elementAt(i)).actionPerformed(a);
	}
    
    public String getText() 
	{
	    return tf.getText();
	}

    public void setText(String s) 
	{
	    tf.setText(s);
	}

    public void addActionListener(ActionListener a) 
	{
	    als.addElement(a);
	}
    
    public void removeActionListener(ActionListener a) 
	{
	    als.removeElement(a);
	}
    
}


