import javax.swing.*;
import javax.swing.table.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;

public class TableTest extends JFrame implements ActionListener {

    private JTable table;
    private JScrollPane scroll;
    private JComboBox lafCombo;
    private JComboBox dropCombo;
    private JComboBox emptyModel = new JComboBox(new String[]{"NORMAL", "EMPTY", "NOROWS"});
    private JCheckBox allowEmptySpace = new JCheckBox("Allow Drop on Empty Space", false);
    private JCheckBox rtl = new JCheckBox("R to L", false);

    private static String[] LAFNames;
    private static String[] LAFClassNames;

    static {
        UIManager.LookAndFeelInfo[] info = UIManager.getInstalledLookAndFeels();
        int length = info.length;
        LAFNames = new String[length];
        LAFClassNames = new String[length];

        for(int i=0; i < info.length; i++) {
            LAFNames[i] = info[i].getName();
            LAFClassNames[i] = info[i].getClassName();
            //System.out.println("Name: " + LAFNames[i] +  " ClassName: " + LAFClassNames[i]);
        }
    }

    private TableModel getTableModel() {
        String[] columnNames = {"Column 0", "Column 1", "Column 2", "Column 3", "Column 4"};
        String[][] data = {{"Table 00, 00", "Table 00, 01", "Table 00, 02", "Table 00, 03", "Table 00, 04"},
                           {"Table 01, 00", "Table 01, 01", "Table 01, 02", "Table 01, 03", "Table 01, 04"},
                           {"Table 02, 00", "Table 02, 01", "Table 02, 02", "Table 02, 03", "Table 02, 04"},
                           {"Table 03, 00", "Table 03, 01", "Table 03, 02", "Table 03, 03", "Table 03, 04"},
                           {"Table 04, 00", "Table 04, 01", "Table 04, 02", "Table 04, 03", "Table 04, 04"},
                           {"Table 05, 00", "Table 05, 01", "Table 05, 02", "Table 05, 03", "Table 05, 04"},
                           {"Table 06, 00", "Table 06, 01", "Table 06, 02", "Table 06, 03", "Table 06, 04"},
                           {"Table 07, 00", "Table 07, 01", "Table 07, 02", "Table 07, 03", "Table 07, 04"},
                           {"Table 08, 00", "Table 08, 01", "Table 08, 02", "Table 08, 03", "Table 08, 04"},
                           {"Table 09, 00", "Table 09, 01", "Table 09, 02", "Table 09, 03", "Table 09, 04"},
                           {"Table 10, 00", "Table 10, 01", "Table 10, 02", "Table 10, 03", "Table 10, 04"}};

        return new DefaultTableModel(data, columnNames);
    }

   private TableModel emptyModel() {
       return new DefaultTableModel(new String[0][0], new String[0]);
   }

   private TableModel colOnlyModel() {
       String[] columnNames = {"Column 0", "Column 1", "Column 2", "Column 3", "Column 4"};
       return new DefaultTableModel(new String[0][0], columnNames);
   }

    public TableTest() {
        super("TableTest");

        table = new JTable(getTableModel()) {
            public boolean getScrollableTracksViewportHeight() {
                if (getParent() instanceof JViewport) {
                    return (((JViewport)getParent()).getHeight() > getPreferredSize().height);
                }
                return false;
            }
        };

        table.setRowSelectionAllowed(true);
        table.setColumnSelectionAllowed(false);
        table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        table.setIntercellSpacing(new Dimension(10, 10));
        table.setRowHeight(table.getRowHeight() + 20);

        table.setTransferHandler(new TransferHandler() {

            public boolean canImport(TransferHandler.TransferSupport info) {
                JTable.DropLocation dl = (JTable.DropLocation)info.getDropLocation();
                if (!allowEmptySpace.isSelected() &&
                        dl.getRow() == -1 && dl.getColumn() == -1) {

                    return false;
                }

                return true;
            }

            public boolean importData(TransferHandler.TransferSupport info) {
                if (!info.isDrop()) {
                    return false;
                }

                JTable.DropLocation dl = (JTable.DropLocation)info.getDropLocation();

                if (dl.getRow() == -1 && dl.getColumn() == -1) {
                    displayDropLocation("Dropped in empty space");
                    return false;
                }

                if (dl.isInsertRow() && dl.isInsertColumn()) {
                    String row;
                    String col;
                    if (dl.getRow() == 0) {
                        row = "at the top of the table";
                    } else if (dl.getRow() == table.getRowCount()) {
                        row = "at the bottom of the table";
                    } else {
                        row = "at position " + dl.getRow();
                    }

                    if (dl.getColumn() == 0) {
                        col = "before all columns";
                    } else if (dl.getColumn() == table.getColumnCount()) {
                        col = "after all columns";
                    } else {
                        col = "at position " + dl.getColumn();
                    }

                    displayDropLocation("Insert a new row " + row + " and column " + col);
                } else if (dl.isInsertRow()) {
                    if (dl.getRow() == 0) {
                        displayDropLocation("Insert a new row at the top of the table, in column " + dl.getColumn());
                    } else if (dl.getRow() == table.getRowCount()) {
                        displayDropLocation("Insert a new row at the bottom of the table, in column " + dl.getColumn());
                    } else {
                        displayDropLocation("Insert a new row at position " + dl.getRow() + ", in column " + dl.getColumn());
                    }
                } else if (dl.isInsertColumn()) {
                    if (dl.getColumn() == 0) {
                        displayDropLocation("Insert a new column before all columns, in row " + dl.getRow());
                    } else if (dl.getColumn() == table.getColumnCount()) {
                        displayDropLocation("Insert a new column after all columns, in row " + dl.getRow());
                    } else {
                        displayDropLocation("Insert a new column at position " + dl.getColumn() + ", in row " + dl.getRow());
                    }
                } else {
                    String value = table.getValueAt(dl.getRow(), dl.getColumn()).toString();
                    displayDropLocation("Dropped on top of \"" + value + "\"");
                }

                return false;
            }
        });

        JList dragFrom = new JList(new String[] {"Drag From Here"});
        dragFrom.setDragEnabled(true);
        dragFrom.setBorder(BorderFactory.createLoweredBevelBorder());
        getContentPane().add(dragFrom, BorderLayout.NORTH);

        rtl.addActionListener(this);
        emptyModel.addActionListener(this);
        scroll = new JScrollPane(table);
        getContentPane().add(scroll, BorderLayout.CENTER);

        lafCombo = new JComboBox(LAFNames);

        dropCombo = new JComboBox(new String[] {"USE_SELECTION",
                                                "ON",
                                                "INSERT",
                                                "INSERT_ROWS",
                                                "INSERT_COLS",
                                                "ON_OR_INSERT",
                                                "ON_OR_INSERT_ROWS",
                                                "ON_OR_INSERT_COLS"});

        lafCombo.addActionListener(this);
        dropCombo.addActionListener(this);

        JPanel bottom = new JPanel(new GridLayout(2,1));
        JPanel bottom1 = new JPanel();
        JPanel bottom2 = new JPanel();
        bottom1.add(new JLabel("LAF "));
        bottom1.add(lafCombo);
        bottom1.add(new JLabel("Table Model "));
        bottom1.add(rtl);
        bottom1.add(emptyModel);
        bottom2.add(allowEmptySpace);
        bottom2.add(new JLabel("  Drop Mode "));
        bottom2.add(dropCombo);

        bottom.add(bottom1);
        bottom.add(bottom2);
        getContentPane().add(bottom, BorderLayout.SOUTH);

        final String[][] instructionsSet =
        {
            {
                "1. Make sure the selection of \"Drop Mode\" is on \"USE_SELECTION\"",
                    "2. At the top, you'll see a drag source \"Drag From Here\" - begin a " +
                    "drag operation from that text",
                    "3. Start dragging over the table and notice that the selection row " +
                    "changes to indicate the drop location. That is, the whole row selection" +
                    " changes (in Metal, lighter blue will indicate the cell you are over).",
                    "4. Drop on top of any item - a dialog will indicate which item you dropped on",
                    "5. Drag again from the drag source into the table and move the mouse below" +
                    " all of the table items. Notice that the mouse cursor shows that you cannot drop.",
                    "6. Drop here and nothing happens.",
                    "7. At the bottom of the test, check the checkbox \"Allow Drop on Empty Space\"",
                    "8. Drag again from the drag source into the table and move the mouse below" +
                    " all of the table items.",
                    "9. Drop there at the epmty space available at below the table items.",
                    "10. Check whether the dialog indicates you dropped in empty space.",
                    "11. Repeat the above steps for all the Look And Feel listed in the" +
                    " \"LAF:\" ComboBox \n",

                    "Note: If all the above observations were proper, then press \"PASS\" " +
                    "else mark this as \"FAIL\" and enter the remarks, if any."
            },
        {
            "1. Change the selection of \"Drop Mode\" ComboBox to \"ON\"",
                "2. At the top, you'll see a drag source \"Drag From Here\" - begin a " +
                "drag operation from that text",
                "3. Start dragging over the table and notice that the selection stays there" +
                " and drop location indicator will be rendered (only for single cell) along with the drag " +
                "changes to indicate the drop location. That is, the whole row selection" +
                " changes (in Metal, lighter blue will indicate the cell you are over).",
                "4. Drop on top of any item - a dialog will indicate which item you dropped on",
                "5. Drag again from the drag source into the table and move the mouse below" +
                " all of the table items. Notice that the mouse cursor shows that you cannot drop.",
                "6. Drop here and nothing happens.",
                "7. At the bottom of the test, check the checkbox \"Allow Drop on Empty Space\"",
                "8. Drag again from the drag source into the table and move the mouse below" +
                " all of the table items.",
                "9. Drop there at the epmty space available at below the table items.",
                "10. Check whether the dialog indicates you dropped in empty space.",
                "11. Repeat the above steps for all the Look And Feel listed in the" +
                " \"LAF:\" ComboBox \n",

                "Note: If all the above observations were proper, then press \"PASS\" " +
                "else mark this as \"FAIL\" and enter the remarks, if any."
        },
            {
            "1. Change the selection of \"Drop Mode\" ComboBox to \"INSERT_ROWS\"",
                    "2.  Drag from the drag source into the JTable. This time the insert location" +
                    " will be *between* rows and it will be rendered with a horizontal line." +
                    " A shorter line of a different color will indicate the column that you're in.",
                    "3. Drop at the top of the table, before any rows and the dialog will show" +
                    " \"Insert a new row at the top of the table, in column X\" (X will "+
                    " indicate the column you dropped into)",
                    "4. Drag again from the drag source into the table",
                    "5. Drop between any two rows and the dialog will indicate \"Insert a new row" +
                    " at position Y, in column X\" (Y will be the row index where the row should be" +
                    " inserted and X is the column you've dropped into).",
                    "6. In the \"Table Model\" ComboBox that says \"NORMAL\" switch to \"EMPTY\" to" +
                    " show an empty table.",
                    "7. Drag into the empty table and see that dropping is not supported.",
                    "8. Change the \"Table Model\" JComboBox from \"EMPTY\" to \"NO ROWS\"",
                    "9. Drag again from the drag source and drop into the table",
                    "10. Check whether the dialog shows \"Inserted a new row at the top of the table, " +
                    "in column X\" (X will indicate the column you dropped into)",
                    "11. Repeat the above steps for all the Look And Feel listed in the" +
                    " \"LAF:\" ComboBox \n",

                    "Note: If all the above observations were proper, then press \"PASS\" " +
                    "else mark this as \"FAIL\" and enter the remarks, if any."
        },
        {
            "1. Change the selection of \"Drop Mode\" ComboBox to \"INSERT_COLS\"",
                "2. Drag from the drag source into the JTable.",
                "3. This time the insert location will be *between* columns and it will be" +
                " rendered as a vertical line. A shorter line of a different color will" +
                "  indicate the row that you're in.",
                "4. Drop at the left of the table, before any columns and the dialog will show" +
                " \"Insert a new column before all columns, in row X\" (X will indicate the" +
                " row you dropped into)",
                "5. Drag from the drag source into the JTable.",
                "6. Drop at the right of the table, after all columns and the dialog will show" +
                " \"Insert a new column after all columns, in row X\" (X will indicate the row" +
                " you dropped into)",
                "7. Drag again from the drag source into the JTable.",
                "8. Drop between any two columns and the dialog will indicate \"Insert a new column" +
                " at position Y, in row X\" (Y will be the column index where the column should be" +
                " inserted and X is the row you've dropped into).",
                "9. Change the \"Table Model\" JComboBox from \"NORMAL\" to \"EMPTY\"",
                "10. Drag into the empty table and see that dropping is not supported.",
                "11. Change the \"Table Model\" JComboBox from \"EMPTY\" to \"NO ROWS\"",
                "12. Drag into the empty table and see that dropping is not supported. ",
                "13. Repeat the above steps for all the Look And Feel listed in the" +
                " \"LAF:\" ComboBox \n",

                "Note: If all the above observations were proper, then press \"PASS\" " +
                "else mark this as \"FAIL\" and enter the remarks, if any."
        },
        {
            "1. Change the selection of \"Drop Mode\" ComboBox to \"INSERT\"" +
                " Look at the cell that says \"Table 01, 01\" - we'll do all testing with this cell.",
                "2. Drag from the drag source into the JTable.",
                "3. Drag from the drag source into \"Upper left corner of the cell\" - the insert line" +
                " should run horizontally above the cell and vertically to the left of the cell.",
                "4. Drop and the dialog should say \"Insert a new row at position 1, and column at" +
                " position 1\"",
                "5. Drag again from the drag source into the JTable.",
                "6. Drag into region \"Left Middle portion of the cell\"- the insert line should run" +
                " vertically to the left of the cell.",
                "7. Drop and the dialog should say \"Insert a new column at position 1, in row 1\"",
                "8. Drag from the drag source into region \" Upper Middle Portion of the Cell \" - the " +
                " insert line should run horizontally above the cell.",
                "9. Drop and the dialog should say \"Insert a new row at position 1 in column 1\"",
                "10. Repeat the above steps for all the Look And Feel listed in the" +
                " \"LAF:\" ComboBox \n",

                "Note: If all the above observations were proper, then press \"PASS\" " +
                "else mark this as \"FAIL\" and enter the remarks, if any."
        }
        };
        final String[] exceptionsSet =
        {
            "Checks whether the selection changes according to the drag and drop lcoation " +
                "on USE_SELCTION drop mode",
            "Checks whether the selection stays and new selection appears along with drag to" +
                "indicate the drop lcoation on ON drop mode",
            "Checks whether the drop location is calculated for the drop mode INSERT_ROWS",
            "Checks whether the drop location is calculated for the drop mode INSERT_COLS",
            "Checks whether the drop location is calculated for the drop mode INSERT"
        };

        Sysout.setInstructionsWithExceptions(instructionsSet,exceptionsSet);

        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent event) {
                if (Sysout.getDoneTestsCount() != exceptionsSet.length) {
                    Sysout.addFailureMessage("Some tests were not done!");
                }
                if (Sysout.failStatus() || Sysout.getDoneTestsCount() != exceptionsSet.length) {
                    System.err.println("\nFollowing check(s) failed:");
                    System.err.println(Sysout.getFailureMessages());
                    System.exit(1);
                } else {
                    System.out.println("Test passed");
                    System.exit(0);
                }
            }
        });
    }

    private void displayDropLocation(final String string) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JOptionPane.showMessageDialog(scroll, string);
            }
        });
    }

    public void actionPerformed(ActionEvent ae) {
        Object source = ae.getSource();
        if (source == lafCombo) {
            changeLAF();
        } else if (source == dropCombo) {
            changeDM();
        } else if (source == emptyModel) {
            changeModel();
        } else if (source == rtl) {
            changeRTL();
        }
    }

    private void changeRTL() {
        if (rtl.isSelected()) {
            scroll.applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
        } else {
            scroll.applyComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
        }
    }

    private void changeModel() {
        Object val = emptyModel.getSelectedItem();
        if (val == "NORMAL") {
            table.setModel(getTableModel());
        } else if (val == "EMPTY") {
            table.setModel(emptyModel());
        } else if (val == "NOROWS") {
            table.setModel(colOnlyModel());
        }
    }

    private void changeDM() {
        Object val = dropCombo.getSelectedItem();
        if (val == "USE_SELECTION") {
            table.setDropMode(DropMode.USE_SELECTION);
        } else if (val == "ON") {
            table.setDropMode(DropMode.ON);
        } else if (val == "INSERT") {
            table.setDropMode(DropMode.INSERT);
        } else if (val == "INSERT_ROWS") {
            table.setDropMode(DropMode.INSERT_ROWS);
        } else if (val == "INSERT_COLS") {
            table.setDropMode(DropMode.INSERT_COLS);
        } else if (val == "ON_OR_INSERT") {
            table.setDropMode(DropMode.ON_OR_INSERT);
        } else if (val == "ON_OR_INSERT_ROWS") {
            table.setDropMode(DropMode.ON_OR_INSERT_ROWS);
        } else if (val == "ON_OR_INSERT_COLS") {
            table.setDropMode(DropMode.ON_OR_INSERT_COLS);
        }
    }

   private void changeLAF() {
        int lafIndex = lafCombo.getSelectedIndex();
        String className = null;
        javax.swing.plaf.metal.MetalTheme theme = null;

        className = LAFClassNames[lafIndex];

        try {
            if (theme != null) {
                javax.swing.plaf.metal.MetalLookAndFeel.setCurrentTheme(theme);
            }
            UIManager.setLookAndFeel(className);
            SwingUtilities.updateComponentTreeUI(this);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                TableTest test = new TableTest();
                test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                test.setSize(800, 600);
                test.setLocationRelativeTo(null);
                test.setVisible(true);
            }
        });
    }
}
/**
This is part of the standard test machinery.
It creates a dialog (with the instructions), and is the interface
for sending text messages to the user.
To print the instructions, send an array of strings to Sysout.createDialog
WithInstructions method.  Put one line of instructions per array entry.
To display a message for the tester to see, simply call Sysout.println
with the string to be displayed.
This mimics System.out.println but works within the test harness as well
as standalone.
*/

class Sysout {

    public static TestDialog dialog;

    public static void createDialogWithInstructions( String[] instructions )
    {
        dialog = new TestDialog( new Frame(), "Instructions" );
        dialog.printInstructions( instructions );
        dialog.show();
        println( "Any messages for the tester will display here." );
    }

    public static void createDialog( )
    {
        dialog = new TestDialog( new Frame(), "Instructions" );
        String[] defInstr = { "Instructions will appear here. ", "" } ;
        dialog.printInstructions( defInstr );
        dialog.show();
        println( "Any messages for the tester will display here." );
    }


    public static void printInstructions( String[] instructions ) {
        if (dialog != null) {
            dialog.printInstructions( instructions );
        }
    }


    public static void println( String messageIn )
    {
        if (dialog != null) {
            dialog.displayMessage( messageIn );
        }
        System.out.println(messageIn);
    }

    public static void setInstructionsWithExceptions(
        String instructionsSet[][],String exceptionsSet[]) {
        createDialogWithInstructions(instructionsSet[0]);
        dialog.setInstructions(instructionsSet);
        dialog.setExceptionMessages(exceptionsSet);
    }

    public static String getFailureMessages()   {
        return dialog.failureMessages;
    }

    public static boolean failStatus()  {
        return dialog.failStatus;
    }

    public static int getDoneTestsCount() {
        return dialog.exceptionCounter;
    }

    public static void addFailureMessage(String failMessage) {
        System.err.println("FAILURE: " + failMessage);
        dialog.failureMessages = dialog.failureMessages + "\n" + failMessage;
        dialog.failStatus = true;
    }

}// Sysout  class

/**
This is part of the standard test machinery.  It provides a place for the
test instructions to be displayed, and a place for interactive messages
to the user to be displayed.
To have the test instructions displayed, see Sysout.
To have a message to the user be displayed, see Sysout.
Do not call anything in this dialog directly.
*/
class TestDialog extends Dialog {

    TextArea instructionsText;
    TextArea messageText;
    int maxStringLength = 65;

    Panel assertPanel;
    Button assertPass,assertFail,remarks;
    HandleAssert handleAssert;
    boolean failStatus=false;
    int instructionCounter=0;
    String instructions[][];
    int exceptionCounter=0;
    String exceptionMessages[];
    String failureMessages="";
    String remarksMessage=null;
    RemarksDialog remarksDialog;

    //DO NOT call this directly, go through Sysout
    public TestDialog(Frame frame, String name) {
        super(frame, name);
        int scrollBoth = TextArea.SCROLLBARS_BOTH;
        instructionsText = new TextArea( "", 14, maxStringLength, scrollBoth );
        add("North", instructionsText);

        messageText = new TextArea("", 10, maxStringLength, scrollBoth);
        add("Center", messageText);

        assertPanel = new Panel(new FlowLayout());
        assertPass=new Button("Assertion Pass");
        assertPass.setName("Assertion Pass");
        assertFail=new Button("Assertion Fail");
        assertFail.setName("Assertion Fail");
        remarks = new Button("Assertion Fail Remarks");
        remarks.setEnabled(false);
        remarks.setName("Assertion Remarks");
        assertPanel.add(assertPass);
        assertPanel.add(assertFail);
        assertPanel.add(remarks);
        handleAssert = new HandleAssert();
        assertPass.addActionListener(handleAssert);
        assertFail.addActionListener(handleAssert);
        remarks.addActionListener(handleAssert);
        add("South",assertPanel);
        pack();

        show();
    }// TestDialog()

    //DO NOT call this directly, go through Sysout
    public void printInstructions( String[] instructions )
    {
        //Clear out any current instructions
        instructionsText.setText( "" );

        //Go down array of instruction strings

        String printStr, remainingStr;
        for( int i=0; i < instructions.length; i++) {
            //chop up each into pieces maxSringLength long
            remainingStr = instructions[ i ];
            while (remainingStr.length() > 0) {
                //if longer than max then chop off first max chars to print
                if (remainingStr.length() >= maxStringLength) {
                    //Try to chop on a word boundary
                    int posOfSpace = remainingStr.lastIndexOf(' ', maxStringLength - 1);

                    if (posOfSpace <= 0) {
                        posOfSpace = maxStringLength - 1;
                    }

                    printStr = remainingStr.substring(0, posOfSpace + 1);
                    remainingStr = remainingStr.substring(posOfSpace + 1);
                } else {
                    //else just print
                    printStr = remainingStr;
                    remainingStr = "";
                }

                instructionsText.append( printStr + "\n" );

            }// while

        }// for

    }//printInstructions()

    //DO NOT call this directly, go through Sysout
    public void displayMessage(String messageIn)
    {
        messageText.append(messageIn + "\n");
    }

    public void emptyMessage()   {
        messageText.setText("");
    }

    public void setInstructions(String insStr[][])    {
        instructions = insStr;
    }

    public void setExceptionMessages(String exceptionMessages[])   {
        this.exceptionMessages = exceptionMessages;
    }

    class HandleAssert implements ActionListener   {
        public void actionPerformed(ActionEvent ae)    {
            if (remarks.equals(ae.getSource()))  {
                remarksDialog = new RemarksDialog(TestDialog.this,
                                                  "Assertion Remarks Dialog", true);
                remarks.setEnabled(false);
                if (remarksMessage != null)
                    failureMessages += ". User Remarks: " + remarksMessage;
            }
            else {
                if (instructionCounter<instructions.length-1) {
                    emptyMessage();
                    instructionCounter++;
                    printInstructions(instructions[instructionCounter]);
                } else {
                    emptyMessage();
                    displayMessage("Testcase Completed");
                    displayMessage("Close the Table Test frame to exit the testcase");
                    assertPass.setEnabled(false);
                    assertFail.setEnabled(false);
                }

                if (assertPass.equals(ae.getSource()))    {
                    // anything to be done in future
                } else if (assertFail.equals(ae.getSource()))   {
                    remarks.setEnabled(true);
                    if(!failStatus)
                        failStatus = true;
                    if (exceptionCounter < exceptionMessages.length) {
                        failureMessages = failureMessages + "\n" +
                            exceptionMessages[exceptionCounter];
                    }
                }
                exceptionCounter++;
            }
        }
    }

    class RemarksDialog extends Dialog  implements ActionListener{
        Panel rootPanel,remarksPanel;
        TextArea textarea;
        Button addRemarks,cancelRemarks;
        public RemarksDialog(Dialog owner,String title,boolean modal)  {
            super(owner,title,modal);
            rootPanel = new Panel(new BorderLayout());
            remarksPanel = new Panel(new FlowLayout());
            textarea = new TextArea(5,30);
            addRemarks=new Button("Add Remarks");
            addRemarks.addActionListener(this);
            cancelRemarks = new Button("Cancel Remarks");
            cancelRemarks.addActionListener(this);
            remarksPanel.add(addRemarks);
            remarksPanel.add(cancelRemarks);
            rootPanel.add(textarea,"Center");
            rootPanel.add(remarksPanel,"South");
            add(rootPanel);
            setBounds(150,150,400,200);
            setVisible(true);
        }

        public void actionPerformed(ActionEvent ae) {
            remarksMessage=null;
            if(addRemarks.equals(ae.getSource()))  {
                String msg = textarea.getText().trim();
                if (msg.length() > 0)
                    remarksMessage = msg;
            }
            dispose();
        }

    }

}
