/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * jpnUseCase.java
 *
 * Created on May 1, 2010, 10:11:10 PM
 */
package uce.ui;

import java.awt.Component;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import org.antlr.runtime.tree.CommonTree;
import uce.ui.components.jpnCondition;
import uce.ui.components.jpnExtraCourse;

/**
 *
 * @author chepa
 */
public class jpnUseCase extends javax.swing.JPanel {

	private static final int SENTENCE_NUMBER_COLUMN = 0;
	private static final int SENTENCE_COLUMN = 1;

	private class ExtCourseList {

		private List<String> m_CourseList = new ArrayList<String>();

		public void addCourse(String courseName) {
			if (!m_CourseList.contains(courseName)) {
				m_CourseList.add(courseName);
			}
		}

		@Override
		public String toString() {
			StringBuffer bf = new StringBuffer();
			for (String course : m_CourseList) {
				bf.append(course + ", ");
			}
			return bf.toString();
		}
	}

	private class ExtCoursePopupMenu extends JPopupMenu {

		private JMenuItem m_Alt, m_Exp;
		private Map<Integer, Integer> m_AltCounts = new HashMap<Integer, Integer>(),
				m_ExpCounts = new HashMap<Integer, Integer>();
		private int m_Row;

		public void setRow(int row) {
			m_Row = row;
		}

		public ExtCoursePopupMenu() {
			super();
			m_Alt = new JMenuItem("Add Alternate Course");
			m_Exp = new JMenuItem("Add Exception Course");
			ActionListener listener = new ActionListener() {

				public void actionPerformed(ActionEvent e) {
					String courseName = "", courseNumber = "";
					int val = 1;
					if (e.getSource() == m_Alt) {
						if (m_AltCounts.containsKey(m_Row)) {
							val = m_AltCounts.get(m_Row);
						}
						courseName = "Alternate Course";
						m_AltCounts.put(m_Row, val + 1);
					} else if (e.getSource() == m_Exp) {
						if (m_ExpCounts.containsKey(m_Row)) {
							val = m_ExpCounts.get(m_Row);
						}
						courseName = "Exception Course";
						m_ExpCounts.put(m_Row, val + 1);
					}
					if (courseName.isEmpty()) {
						return;
					}
					courseNumber = (1 + m_Row) + "." + val;
					jpnExtraCourse extraCourse = new jpnExtraCourse(courseName + " " + courseNumber);
					String shortName = courseName.substring(0, 1) + courseNumber;
					jtbUseCase.add(shortName, extraCourse);
					Object obj = tblNormal.getValueAt(m_Row, 2);
					ExtCourseList list;
					if (obj == null || !(obj instanceof ExtCourseList)) {
						list = new ExtCourseList();
					} else {
						list = (ExtCourseList) obj;
					}
					list.addCourse(shortName);
					tblNormal.setValueAt(list, m_Row, 2);
				}
			};
			m_Alt.addActionListener(listener);
			m_Exp.addActionListener(listener);
			this.add(m_Alt);
			this.add(m_Exp);
		}
	}

	/** Creates new form jpnUseCase */
	public jpnUseCase() {
		initComponents();
		tblNormal.addMouseListener(new MouseAdapter() {

			ExtCoursePopupMenu m_pop = new ExtCoursePopupMenu();

			@Override
			public void mouseClicked(MouseEvent e) {
				if (e.getButton() == MouseEvent.BUTTON3) {
					for (int i = 0; i < tblNormal.getRowCount(); i++) {
						Rectangle rect = tblNormal.getCellRect(i, SENTENCE_COLUMN, true);
						if (rect.contains(e.getX(), e.getY())) {
							m_pop.setRow(i);
							m_pop.show(e.getComponent(), e.getX(), e.getY());
							break;
						}
					}
				}
			}
		});

		tblNormal.addComponentListener(new ComponentAdapter() {

			@Override
			public void componentResized(ComponentEvent e) {
				super.componentResized(e);
				int width = tblNormal.getWidth();
				double[] aRatio = new double[]{.1, .6, .3};
				for (int i = 0; i < aRatio.length; i++) {
					tblNormal.getColumnModel().getColumn(i).setMinWidth((int) (width * aRatio[i]));
					tblNormal.getColumnModel().getColumn(i).setMaxWidth((int) (width * aRatio[i]));
					tblNormal.getColumnModel().getColumn(i).setWidth((int) (width * aRatio[i]));
				}
			}
		});
	}

	/**
	 * Adds given suggestions to the current statement textbox as a tooltip
	 * @param lstSuggestions
	 * List of string suggestions
	 */
	public void setSuggestions(List<String> lstSuggestions) {
		Component c = tblNormal.getEditorComponent();
		if (c == null) {
			return;
		}
		TableCellEditor edt = tblNormal.getCellEditor();
		if (edt instanceof SentenceCellEditor) {
			SentenceCellEditor editor = (SentenceCellEditor) edt;
			editor.setSuggestions(lstSuggestions);
		}
	}

	public List<String> getSentences() {
		List<String> lstSentences = new ArrayList<String>();
		for (int i = 0; i < tblNormal.getRowCount(); i++) {
			if (tblNormal.getValueAt(i, 1) != null) {
				lstSentences.add(tblNormal.getValueAt(i, 1).toString());
			}
		}
		return lstSentences;
	}


    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jtbUseCase = new javax.swing.JTabbedPane();
        pnlInfo = new javax.swing.JPanel();
        pnlUCName = new javax.swing.JPanel();
        lblUCName = new javax.swing.JLabel();
        txtUCName = new javax.swing.JTextField();
        pnlUCContext = new javax.swing.JPanel();
        lblUCContext = new javax.swing.JLabel();
        txtUCContext = new javax.swing.JTextField();
        pnlUCScope = new javax.swing.JPanel();
        lblUCScope = new javax.swing.JLabel();
        txtUCScope = new javax.swing.JTextField();
        pnlUCLevel = new javax.swing.JPanel();
        lblUCLevel = new javax.swing.JLabel();
        cmbLevel = new javax.swing.JComboBox();
        pnlUCPrimAct = new javax.swing.JPanel();
        lblUCPrimAct = new javax.swing.JLabel();
        txtUCPrimAct = new javax.swing.JTextField();
        pnlUCTrigger = new javax.swing.JPanel();
        lblUCTrigger = new javax.swing.JLabel();
        txtUCTrigger = new javax.swing.JTextField();
        chkTrigger = new javax.swing.JCheckBox();
        pnlNormal = new javax.swing.JPanel();
        jSplitPane1 = new javax.swing.JSplitPane();
        jSplitPane2 = new javax.swing.JSplitPane();
        jpnPrecond = new jpnCondition("Precondition(s)");
        jpnPostcond = new jpnCondition("Postcondition(s)");
        jScrollPane1 = new javax.swing.JScrollPane();
        tblNormal = new javax.swing.JTable();

        pnlInfo.setLayout(new java.awt.GridLayout(15, 1));

        lblUCName.setText("Name :");

        javax.swing.GroupLayout pnlUCNameLayout = new javax.swing.GroupLayout(pnlUCName);
        pnlUCName.setLayout(pnlUCNameLayout);
        pnlUCNameLayout.setHorizontalGroup(
            pnlUCNameLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlUCNameLayout.createSequentialGroup()
                .addComponent(lblUCName, javax.swing.GroupLayout.PREFERRED_SIZE, 88, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(36, 36, 36)
                .addComponent(txtUCName, javax.swing.GroupLayout.PREFERRED_SIZE, 310, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(309, 309, 309))
        );
        pnlUCNameLayout.setVerticalGroup(
            pnlUCNameLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnlUCNameLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                .addComponent(lblUCName, javax.swing.GroupLayout.DEFAULT_SIZE, 26, Short.MAX_VALUE)
                .addComponent(txtUCName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );

        pnlInfo.add(pnlUCName);

        lblUCContext.setText("Context :");

        javax.swing.GroupLayout pnlUCContextLayout = new javax.swing.GroupLayout(pnlUCContext);
        pnlUCContext.setLayout(pnlUCContextLayout);
        pnlUCContextLayout.setHorizontalGroup(
            pnlUCContextLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlUCContextLayout.createSequentialGroup()
                .addComponent(lblUCContext, javax.swing.GroupLayout.PREFERRED_SIZE, 88, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(36, 36, 36)
                .addComponent(txtUCContext, javax.swing.GroupLayout.PREFERRED_SIZE, 310, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(309, 309, 309))
        );
        pnlUCContextLayout.setVerticalGroup(
            pnlUCContextLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnlUCContextLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                .addComponent(lblUCContext, javax.swing.GroupLayout.DEFAULT_SIZE, 26, Short.MAX_VALUE)
                .addComponent(txtUCContext, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );

        pnlInfo.add(pnlUCContext);

        lblUCScope.setText("Scope :");

        javax.swing.GroupLayout pnlUCScopeLayout = new javax.swing.GroupLayout(pnlUCScope);
        pnlUCScope.setLayout(pnlUCScopeLayout);
        pnlUCScopeLayout.setHorizontalGroup(
            pnlUCScopeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlUCScopeLayout.createSequentialGroup()
                .addComponent(lblUCScope, javax.swing.GroupLayout.PREFERRED_SIZE, 84, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(40, 40, 40)
                .addComponent(txtUCScope, javax.swing.GroupLayout.PREFERRED_SIZE, 310, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(309, 309, 309))
        );
        pnlUCScopeLayout.setVerticalGroup(
            pnlUCScopeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnlUCScopeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                .addComponent(lblUCScope, javax.swing.GroupLayout.DEFAULT_SIZE, 26, Short.MAX_VALUE)
                .addComponent(txtUCScope, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );

        pnlInfo.add(pnlUCScope);

        lblUCLevel.setText("Level :");

        cmbLevel.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "User-Goal", "Sub-function", "Summary" }));

        javax.swing.GroupLayout pnlUCLevelLayout = new javax.swing.GroupLayout(pnlUCLevel);
        pnlUCLevel.setLayout(pnlUCLevelLayout);
        pnlUCLevelLayout.setHorizontalGroup(
            pnlUCLevelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlUCLevelLayout.createSequentialGroup()
                .addComponent(lblUCLevel, javax.swing.GroupLayout.PREFERRED_SIZE, 92, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(33, 33, 33)
                .addComponent(cmbLevel, javax.swing.GroupLayout.PREFERRED_SIZE, 225, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(393, 393, 393))
        );
        pnlUCLevelLayout.setVerticalGroup(
            pnlUCLevelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnlUCLevelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                .addComponent(lblUCLevel, javax.swing.GroupLayout.DEFAULT_SIZE, 35, Short.MAX_VALUE)
                .addComponent(cmbLevel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );

        pnlInfo.add(pnlUCLevel);

        lblUCPrimAct.setText("Primary Actor :");

        javax.swing.GroupLayout pnlUCPrimActLayout = new javax.swing.GroupLayout(pnlUCPrimAct);
        pnlUCPrimAct.setLayout(pnlUCPrimActLayout);
        pnlUCPrimActLayout.setHorizontalGroup(
            pnlUCPrimActLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlUCPrimActLayout.createSequentialGroup()
                .addComponent(lblUCPrimAct)
                .addGap(40, 40, 40)
                .addComponent(txtUCPrimAct, javax.swing.GroupLayout.PREFERRED_SIZE, 310, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(308, 308, 308))
        );
        pnlUCPrimActLayout.setVerticalGroup(
            pnlUCPrimActLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnlUCPrimActLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                .addComponent(lblUCPrimAct, javax.swing.GroupLayout.DEFAULT_SIZE, 26, Short.MAX_VALUE)
                .addComponent(txtUCPrimAct, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );

        pnlInfo.add(pnlUCPrimAct);

        lblUCTrigger.setText("Trigger :");

        chkTrigger.setText("Enabled");

        javax.swing.GroupLayout pnlUCTriggerLayout = new javax.swing.GroupLayout(pnlUCTrigger);
        pnlUCTrigger.setLayout(pnlUCTriggerLayout);
        pnlUCTriggerLayout.setHorizontalGroup(
            pnlUCTriggerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlUCTriggerLayout.createSequentialGroup()
                .addComponent(lblUCTrigger, javax.swing.GroupLayout.PREFERRED_SIZE, 87, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(43, 43, 43)
                .addComponent(txtUCTrigger, javax.swing.GroupLayout.PREFERRED_SIZE, 310, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addComponent(chkTrigger)
                .addContainerGap(217, Short.MAX_VALUE))
        );
        pnlUCTriggerLayout.setVerticalGroup(
            pnlUCTriggerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnlUCTriggerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                .addComponent(lblUCTrigger, javax.swing.GroupLayout.DEFAULT_SIZE, 26, Short.MAX_VALUE)
                .addComponent(chkTrigger)
                .addComponent(txtUCTrigger, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );

        pnlInfo.add(pnlUCTrigger);

        jtbUseCase.addTab("General Information", pnlInfo);

        jSplitPane1.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);

        jSplitPane2.setDividerSize(3);
        jSplitPane2.setResizeWeight(0.5);

        LayoutManager preCondmanager = jpnPrecond.getLayout();
        jpnPrecond.setBorder(null);
        jpnPrecond.setLayout(null);
        jpnPrecond.setLayout(preCondmanager);
        jSplitPane2.setLeftComponent(jpnPrecond);

        LayoutManager postCondmanager = jpnPostcond.getLayout();
        jpnPostcond.setBorder(null);
        jpnPostcond.setLayout(null);
        jpnPostcond.setLayout(postCondmanager);
        jSplitPane2.setRightComponent(jpnPostcond);

        jSplitPane1.setLeftComponent(jSplitPane2);

        tblNormal.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null, null, null}
            },
            new String [] {
                "Statement #", "Sentence", "Notes"
            }
        ) {
            Class[] types = new Class [] {
                java.lang.String.class, java.lang.String.class, ExtCourseList.class
            };
            boolean[] canEdit = new boolean [] {
                false, true, false
            };

            public Class getColumnClass(int columnIndex) {
                return types [columnIndex];
            }

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
        tblNormal.getTableHeader().setReorderingAllowed(false);
        jScrollPane1.setViewportView(tblNormal);
        tblNormal.getColumnModel().getColumn(0).setResizable(false);
        tblNormal.getColumnModel().getColumn(1).setResizable(false);
        tblNormal.getColumnModel().getColumn(1).setCellEditor(new SentenceCellEditor());
        tblNormal.getColumnModel().getColumn(2).setResizable(false);

        jSplitPane1.setBottomComponent(jScrollPane1);

        javax.swing.GroupLayout pnlNormalLayout = new javax.swing.GroupLayout(pnlNormal);
        pnlNormal.setLayout(pnlNormalLayout);
        pnlNormalLayout.setHorizontalGroup(
            pnlNormalLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 715, Short.MAX_VALUE)
            .addGroup(pnlNormalLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 715, Short.MAX_VALUE))
        );
        pnlNormalLayout.setVerticalGroup(
            pnlNormalLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 525, Short.MAX_VALUE)
            .addGroup(pnlNormalLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 525, Short.MAX_VALUE))
        );

        jtbUseCase.addTab("Normal Course", pnlNormal);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 723, Short.MAX_VALUE)
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addComponent(jtbUseCase, javax.swing.GroupLayout.DEFAULT_SIZE, 723, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 399, Short.MAX_VALUE)
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addComponent(jtbUseCase, javax.swing.GroupLayout.DEFAULT_SIZE, 399, Short.MAX_VALUE))
        );
    }// </editor-fold>                        


    // Variables declaration - do not modify                     
    private javax.swing.JCheckBox chkTrigger;
    private javax.swing.JComboBox cmbLevel;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JSplitPane jSplitPane1;
    private javax.swing.JSplitPane jSplitPane2;
    private javax.swing.JPanel jpnPostcond;
    private javax.swing.JPanel jpnPrecond;
    private javax.swing.JTabbedPane jtbUseCase;
    private javax.swing.JLabel lblUCContext;
    private javax.swing.JLabel lblUCLevel;
    private javax.swing.JLabel lblUCName;
    private javax.swing.JLabel lblUCPrimAct;
    private javax.swing.JLabel lblUCScope;
    private javax.swing.JLabel lblUCTrigger;
    private javax.swing.JPanel pnlInfo;
    private javax.swing.JPanel pnlNormal;
    private javax.swing.JPanel pnlUCContext;
    private javax.swing.JPanel pnlUCLevel;
    private javax.swing.JPanel pnlUCName;
    private javax.swing.JPanel pnlUCPrimAct;
    private javax.swing.JPanel pnlUCScope;
    private javax.swing.JPanel pnlUCTrigger;
    private javax.swing.JTable tblNormal;
    private javax.swing.JTextField txtUCContext;
    private javax.swing.JTextField txtUCName;
    private javax.swing.JTextField txtUCPrimAct;
    private javax.swing.JTextField txtUCScope;
    private javax.swing.JTextField txtUCTrigger;
    // End of variables declaration                   

	    public List<String> getNormalCourse() {
        if (tblNormal.getCellEditor() != null) {
            tblNormal.getCellEditor().stopCellEditing();
        }

        List<String> lstNormalCourse = new ArrayList<String>();
        for (int i = 0; i < tblNormal.getRowCount(); i++) {
            lstNormalCourse.add(tblNormal.getValueAt(i, SENTENCE_COLUMN).toString());
        }
        return lstNormalCourse;
    }

    public void setNormalCourseValidator(CellValidator validator) {
        final SentenceCellEditor sent_editor = (SentenceCellEditor) tblNormal.getColumnModel().getColumn(SENTENCE_COLUMN).getCellEditor();
        sent_editor.addCellEditorListener(new CellEditorListener() {

            public void editingStopped(ChangeEvent e) {
                int row = sent_editor.getRow();
                tblNormal.setValueAt(row + 1, row, SENTENCE_NUMBER_COLUMN);
                //lstSuggestions.setListData(new Object[]{});
                CommonTree tree = sent_editor.getValidator().ValidateText(sent_editor.getCellEditorValue().toString());
                if (tree != null) {
                    JOptionPane.showMessageDialog(getParent(), tree.toStringTree());
                }
                if (row == tblNormal.getRowCount() - 1) {
                    addRow();
                }
            }

            public void editingCanceled(ChangeEvent e) {
                editingStopped(e);
            }
        });
        sent_editor.setValidator(validator);
    }

	public CellValidator getNormalCourseValidator() {
		final SentenceCellEditor sent_editor = (SentenceCellEditor) tblNormal.getColumnModel().getColumn(SENTENCE_COLUMN).getCellEditor();
		return sent_editor.getValidator();
	}

	public void addRow() {
        DefaultTableModel model = (DefaultTableModel) tblNormal.getModel();
        if (model.getValueAt(tblNormal.getRowCount() - 1, SENTENCE_COLUMN).equals("")) {
            return;
        }
        model.insertRow(tblNormal.getRowCount(), new Object[]{"", "", ""});
    }

}

