/*
 * RunManager.java
 *
 * Created on January 24, 2006, 3:44 PM
 *
 * To change this template, choose Tools | Options and locate the template under
 * the Source Creation and Management node. Right-click the template and choose
 * Open. You can then make changes to the template in the Source Editor.
 */
package usda.weru.wmrm;

import java.util.List;
import usda.weru.weps.*;

import usda.weru.util.*;
import java.beans.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;
import com.klg.jclass.table.*;
import com.klg.jclass.table.data.JCVectorDataSource;
import de.schlichtherle.io.File;
import java.awt.CardLayout;
import java.awt.Cursor;
import java.awt.Desktop;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Rectangle;
import java.awt.print.PageFormat;
import org.jdesktop.jdic.desktop.DesktopException;
import usda.weru.weps.reports.ReportManager;

/**
 *
 * @author joelevin
 */
public class Wmrm extends usda.weru.wmrm.gui.Wmrm_n implements JCTableDataListener, PropertyChangeListener, TreeSelectionListener, TreeWillExpandListener, KeyListener, JCResizeCellListener {

    private Application c_app = Application.WMRM;
    private File configFile = new File("wmrm/wmrm_table.xml").getCanOrAbsFile();
    private ConvertedValueCellRenderer c_convertedValueCellRenderer;
    private String c_projectsPath;
    private DataModel c_model;
    private TableMeta c_meta;
    private String c_unitsSystem;
    private int c_sortIndex = -1;
    private int c_sortDirection = -999;
    private Weps c_weps;

    /**
     * Creates a new instance of RunManager in standalone mode.
     * @param weps
     */
    public Wmrm(Weps weps) {
        super();
        if (weps == null) {
            weps = new usda.weru.weps.Weps();
        }
        c_weps = weps;

        M_runs.setEnabled(false);
        M_help1.setEnabled(false);
        LT_runs.setEnabled(false);       
        JTR_groups.setEnabled(false);
        CardLayout cards = (CardLayout) loadingCardPanel.getLayout();
        cards.show(loadingCardPanel, "loading");

        setTitle("WMRM");

        setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        LT_runs.setTrackCursor(false);
        LT_runs.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));

        //empty data set while loading
        LT_runs.setDataSource(new JCVectorDataSource(0, 0, null, null, null));

    }

    class InternalWorker extends SwingWorker<Boolean, Runnable> {

        private final Wmrm c_wmrm;

        public InternalWorker(Wmrm wmrm) {
            c_wmrm = wmrm;
        }

        @Override
        protected void process(List<Runnable> chunks) {
            for (Runnable process : chunks) {                
                process.run();
            }
        }

        @Override
        protected Boolean doInBackground() throws Exception {

            //New Model Code, JCTable and JTree
            c_model = new DataModel();

            File runs = c_weps.getRunsLocation();
            if(runs != null){
                c_model.addDirectoryToModel(runs);
            }
            
            c_projectsPath = ConfigData.getDefault().getDataParsed(ConfigData.ProjDir);
            
            File tempFile = new File( ConfigData.getDefault().getDataParsed(ConfigData.CurrentProj));
            DataModel.RunGroup tempGroup = c_model.lookupRunGroup(tempFile);
            if (tempGroup == null) {
                //Need to add the directory to the tree
                tempGroup = c_model.addDirectoryToModel(tempFile);
            }
            c_model.setCurrentProject(tempGroup);


            ConfigData.getDefault().addPropertyChangeListener(c_wmrm);
            ConfigData.getDefault().fireAll(c_wmrm);

            c_unitsSystem = (String) ConfigData.getDefault().getData(ConfigData.Units);


            c_weps.rfd.addPropertyChangeListener(c_wmrm);
            c_weps.rfd.fireAll(c_wmrm);

            c_weps.addPropertyChangeListener(c_wmrm);
            LT_runs.addResizeCellListener(c_wmrm);

            LT_runs.addMouseMotionListener(new MouseMotionAdapter() {

                @Override
                public void mouseMoved(MouseEvent me) {

                    JCCellPosition position = LT_runs.XYToCell(me.getX(), me.getY());
                    int row = position.row;
                    row = c_meta.getDataRow(row);
                    row = row - c_meta.getNumHeaderRows();

                    //adjust row for header
                    int column = c_meta.getDataColumn(position.column);

                    String tooltip = c_model.getTableDataToolTipText(row, column);
                    if (tooltip != null) {
                        LT_runs.setToolTipText(tooltip);
                    }
                    else {
                        LT_runs.setToolTipText(null);
                    }

                }
            });


            return true;
        }

        @Override
        protected void done() {
            //finished loading everything            

            //WMRM listens for add events to reapply the sort order.
            c_model.addTableDataListener(c_wmrm);

            c_meta = new TableMeta(configFile);

            //Link the datasource/meta to the table
            c_meta.linkTable(LT_runs);
            c_meta.setUnitsSystem(c_unitsSystem);

            LT_runs.setColumnHidden(-1, true);   //Hide row numbers
            LT_runs.setAutoscrolls(false);
            LT_runs.setAutoScroll(JCTableEnum.AUTO_SCROLL_NONE);
            LT_runs.setHorizSBPosition(JCTableEnum.POSITION_AT_SIDE);
            LT_runs.setSelectionPolicy(JCTableEnum.SELECT_RANGE);
            LT_runs.setPopupMenuEnabled(false);




            ActionInitiator initiator = new MouseActionInitiator(MouseEvent.BUTTON1, ActionInitiator.NO_MODIFIER_MASK);
            LT_runs.addAction(new TableAction(initiator, TableAction.COLUMN_SORT_ACTION));



            //Code to allow only one row to be selected.
            LT_runs.addSelectListener(new JCSelectAdapter() {

                public void select(JCSelectEvent event) {
                    if (event.getAction() == JCSelectEvent.EXTEND && event.getStartRow() != event.getEndRow()) {
                        event.setCancelled(true);
                    }
                }
            });

             //Setup the tree
            JTR_groups.addTreeSelectionListener(c_wmrm);

            JTR_groups.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
            JTR_groups.addTreeWillExpandListener(c_wmrm);
            JTR_groups.addKeyListener(c_wmrm);

            //Make converted values use the new cell renderer
            c_convertedValueCellRenderer = new ConvertedValueCellRenderer();
            c_convertedValueCellRenderer.setUnitsSystem(c_unitsSystem);
            LT_runs.setCellRenderer(ConvertedValue.class, c_convertedValueCellRenderer);






            LT_runs.addMouseListener(new MouseAdapter() {

                public void mouseClicked(MouseEvent me) {
                    if (me.getClickCount() == 2) {
                        mouseDoubleClicked(me);
                    }
                    else {
                        if (me.getClickCount() == 1) {
                            mouseSingleClicked(me);
                        }
                    }
                }
            });

            c_meta.setDataSource(c_model);
            JTR_groups.setModel(c_model);
            c_meta.setUnitsSystem(c_unitsSystem);
            c_model.fireDataReset();

            M_runs.setEnabled(true);
            M_help1.setEnabled(true);
            LT_runs.setEnabled(true);
            JTR_groups.setEnabled(true);

            CardLayout cards = (CardLayout) loadingCardPanel.getLayout();
            cards.show(loadingCardPanel, "table");
            loadingCircle.setActive(false);

            setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
            LT_runs.setTrackCursor(true);
            LT_runs.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));

            //End New Model Code
            setTitle(c_app.getName() + " - " + c_app.getDescription());
            
            
        }
    }

    public void init() {
        SwingWorker worker = new InternalWorker(this);
        worker.execute();


    }


    //Property Events
    public void propertyChange(PropertyChangeEvent event) {
        if (event.getPropertyName().equals(ConfigData.ProjDir)) {
            c_projectsPath = new File(".", event.getNewValue().toString()).getPath();
        }
        else {
            if (event.getPropertyName().equals(ConfigData.Units)) {
                c_unitsSystem = (String) event.getNewValue();
                c_convertedValueCellRenderer.setUnitsSystem(c_unitsSystem);
                c_meta.setUnitsSystem(c_unitsSystem);
                c_model.fireDataReset();
            }
            else {
                if (event.getPropertyName().equals(ConfigData.CurrentProj)) {
                    File tempFile = new File(Util.parse(event.getNewValue().toString()));
                    DataModel.RunGroup tempGroup = c_model.lookupRunGroup(tempFile);
                    if (tempGroup == null) {
                        //Need to add the directory to the tree
                        tempGroup = c_model.addDirectoryToModel(tempFile);
                    }
                    c_model.setCurrentProject(tempGroup);
                }
                else {
                    if (event.getPropertyName().equals(Weps.WEPS_RUNCREATED)) {
                        c_model.addRunFileToModel(null, new File(event.getNewValue().toString()));
                    }
                    else {
                        if (event.getPropertyName().equals(Weps.WEPS_RUNRESTORED)) {
                            c_model.addRunFileToModel(null, new File(event.getNewValue().toString()));
                        }
                        else {
                            if (ConfigData.DefaultRunsLocation.equals(event.getPropertyName())) {
                                //c_model.addDirectoryToModel(new File(event.getNewValue().toString()));
                            }
                            else {
                                if (event.getPropertyName().equals(RunFileData.RunsLocation)) {
                                    c_model.addDirectoryToModel(new File(event.getNewValue().toString()));
                                }
                            }
                        }
                    }
                }
            }
        }


    }

    private void mouseDoubleClicked(MouseEvent event) {
        int rowIndex = LT_runs.getCellAreaHandler().getRow(event.getX(), event.getY());
        //Double clicked a header cell.
        if (rowIndex < c_meta.getNumHeaderRows()) {
            return;
        }
        rowIndex = c_meta.getDataRow(rowIndex) - c_meta.getNumHeaderRows();

        int columnIndex = LT_runs.getCellAreaHandler().getColumn(event.getX(), event.getY());
        TableMeta.ColumnMeta column = c_meta.getColumnMeta(columnIndex);

        RunWrapper run = c_model.getRunWrapper(rowIndex);
        takeActionOnRun(run, column.getAction());
    }

    private void mouseSingleClicked(MouseEvent event) {
        int rowIndex = LT_runs.getCellAreaHandler().getRow(event.getX(), event.getY());
        //Clicked a data cell.
        if (rowIndex >= c_meta.getNumHeaderRows()) {
            return;
        }
        int columnIndex = LT_runs.getCellAreaHandler().getColumn(event.getX(), event.getY());
        //Was a new column clicked?
        if (columnIndex != c_sortIndex) {
            //Set to default direction
            c_sortIndex = columnIndex;
            c_sortDirection = Sort.ASCENDING;
        }
        else {
            //Change sort direction
            switch (c_sortDirection) {
                case Sort.ASCENDING:
                    c_sortDirection = Sort.DESCENDING;
                    break;
                case Sort.DESCENDING:
                    c_sortIndex = -1;
                    c_sortDirection = -100;
            }
        }

        applySort();
    }

    private void applySort() {
        if (c_sortIndex > -1) {
            c_meta.sortByColumn(c_sortIndex, c_sortDirection);
        }
        else {
            c_meta.sortByColumn(c_sortIndex, c_sortDirection);
            c_meta.resetRowMap();
        }
    }

    public void takeActionOnRun(RunWrapper run, String action) {
        if (action.equalsIgnoreCase("open_runsummary")) {
            ReportManager.getDefault().displayReport(run.getDirectory(), ReportManager.REPORT_RUN);
        }
        else if (action.equalsIgnoreCase("open_cropsummary")) {
                ReportManager.getDefault().displayReport(run.getDirectory(), ReportManager.REPORT_CROP);            
        }
        else if (action.equalsIgnoreCase("open_detail")) {
            ReportManager.getDefault().displayReport(run.getDirectory(), ReportManager.REPORT_DETAIL);
        }
        else if (action.equalsIgnoreCase("open_managementsummary")) {
            ReportManager.getDefault().displayReport(run.getDirectory(), ReportManager.REPORT_MANAGEMENT);
        }
        else if (action.equalsIgnoreCase("open_soil")) {
            ReportManager.getDefault().displayReport(run.getDirectory(), ReportManager.REPORT_SOIL);
        }
        else if ("open_runslocation".equalsIgnoreCase(action)){
            try{
                Desktop.getDesktop().open(run.getDirectory().getParentFile());
            }
            catch(Exception de){

            }
        }
    }

    public DataModel getDataModel() {
        return c_model;
    }

    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
    private static void createAndShowGUI() {
        Wmrm multipleRuns = new Wmrm(null);
        multipleRuns.setVisible(true);
    }
    private int[] c_columnSizeCache;

    private void smartColumnResize() {
        if (LT_runs.getHorizSB().isVisible()) {
            smartColumnResizeDown();
        }
        else {
            smartColumnResizeUp();
        }
    }
    private boolean c_ignoreCellResize;

    private void smartColumnResizeUp() {
        checkColumnSizeCache();

        //Find the target size for each column
        int totalWidthOfColumnsWantingResize = 0;
        int totalWidthOfColumns = 0;
        int totalTarget = 0;
        int[] targetWidths = new int[LT_runs.getNumColumns()];
        int[] columnWidths = new int[LT_runs.getNumColumns()];
        for (int columnIndex = 0; columnIndex < LT_runs.getNumColumns(); columnIndex++) {

            int columnWidth = 0;
            int maxTextWidth = 0;
            for (int rowIndex = 0; rowIndex < LT_runs.getNumRows(); rowIndex++) {
                Rectangle bounds = LT_runs.getCellBounds(rowIndex, columnIndex);
                columnWidth = bounds.width;
                columnWidths[columnIndex] = columnWidth;
                Font cellFont = LT_runs.getCellStyle(rowIndex, columnIndex).getFont();
                FontMetrics fm = LT_runs.getGraphics().getFontMetrics(cellFont);
                Object o = LT_runs.getDataSource().getTableDataItem(rowIndex, columnIndex);
                if (o == null) {
                    o = "";
                }
                String text = o.toString();
                int textWidth = fm.stringWidth(text);
                if (textWidth > maxTextWidth) {
                    maxTextWidth = textWidth;
                }
            }
            if (maxTextWidth > columnWidth) {
                targetWidths[columnIndex] = maxTextWidth + 15;
                totalWidthOfColumnsWantingResize += columnWidth;
                totalTarget += targetWidths[columnIndex];
            }
            else {
                targetWidths[columnIndex] = columnWidth;     //Dont't need to change the size;
                totalTarget += targetWidths[columnIndex];
            }
            totalWidthOfColumns += columnWidth;
        }

        //Do we have enough space to expand all the columns to their full desired width?
        if (totalTarget <= LT_runs.getWidth()) {
            //Yes we have enough space, now increase the column widths
            c_ignoreCellResize = true;
            for (int columnIndex = 0; columnIndex < LT_runs.getNumColumns(); columnIndex++) {
                int columnWidth = columnWidths[columnIndex];
                LT_runs.setPixelWidth(columnIndex, targetWidths[columnIndex]);
            }
            c_ignoreCellResize = false;
        }
        else {
            //Do some fancy ratio work to spread the wealth equally
            //Thus, we use a ratio to spread the wealth
            int avaliableSpace = LT_runs.getWidth() - totalWidthOfColumns;
            c_ignoreCellResize = true;
            for (int columnIndex = 0; columnIndex < LT_runs.getNumColumns(); columnIndex++) {
                int columnWidth = columnWidths[columnIndex];
                if (targetWidths[columnIndex] == columnWidth) {
                    continue;
                }
                double ratio = (double) columnWidth / (double) totalWidthOfColumnsWantingResize;
                int newWidth = (int) (ratio * avaliableSpace);
                LT_runs.setPixelWidth(columnIndex, columnWidth + newWidth);
            }
            c_ignoreCellResize = false;
        }





    }

    private void smartColumnResizeDown() {
        checkColumnSizeCache();
        for (int columnIndex = 0; columnIndex < LT_runs.getNumColumns(); columnIndex++) {
            int columnWidth = c_columnSizeCache[columnIndex];
            LT_runs.setPixelWidth(columnIndex, columnWidth);
        }
    }

    private void checkColumnSizeCache() {
        if (c_columnSizeCache == null) {
            buildColumnSizeCache();
            resetColumnSizeCache();
        }
        if (LT_runs.getNumColumns() != c_columnSizeCache.length) {
            buildColumnSizeCache();
            resetColumnSizeCache();
        }
    }

    private void buildColumnSizeCache() {
        c_columnSizeCache = new int[LT_runs.getNumColumns()];
    }

    private void resetColumnSizeCache() {
        checkColumnSizeCache();
        for (int i = 0; i < LT_runs.getNumColumns(); i++) {
            c_columnSizeCache[i] = LT_runs.getPixelWidth(i);
        }
    }

    static public void main(String args[]) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                String mainConfig = "cfg/weps.cfg";
                String userConfig = null;
                //if the user config is not set use the name of the main config file
                if (userConfig == null) {
                    userConfig = About.getUserWeps().getAbsolutePath() + "/" + new File(mainConfig).getName();
                }
                ConfigData.getDefault().load(new File(mainConfig), new File(userConfig));

                createAndShowGUI();
            }
        });
    }

    private int getSelectedRow() {
        if (c_model.getNumRows() > 0 && LT_runs.getSelectedCells() != null && LT_runs.getSelectedCells().size() > 0) {
            JCCellRange range = (JCCellRange) LT_runs.getSelectedCells().toArray()[0];
            return range.start_row;
        }
        else {
            return -1;
        }
    }
    //Menu Events

    protected void MI_about_ActionPerformed(java.awt.event.ActionEvent evt) {
        new usda.weru.util.AboutDialog(this, Application.WMRM).setVisible(true);
    }

    protected void MI_close_ActionPerformed(java.awt.event.ActionEvent evt) {
        dispose();
    }

    protected void MI_addProject_actionPerformed(java.awt.event.ActionEvent evt) {
        WepsFileChooser wfc = new WepsFileChooser(WepsFileChooser.DIR, c_projectsPath, WepsFileChooser.OPEN);
        if(c_projectsPath != null){
            wfc.setCurrentDirectory(new File(c_projectsPath).getAbsoluteFile());
        }
        wfc.homeToolTip(wfc);

        int returnValue = wfc.showOpenDialog(this);
        if (returnValue == wfc.APPROVE_OPTION) {
            File directory = new File(wfc.getSelectedFile());
            c_model.addDirectoryToModel(directory);
        }

    }

    protected void MI_refreshTable_actionPerformed(java.awt.event.ActionEvent evt) {
        setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        c_model.checkRunGroup();
        setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
    }

    protected void MI_addRun_actionPerformed(java.awt.event.ActionEvent evt) {
        WepsFileChooser wfc = new WepsFileChooser(WepsFileChooser.RUN, c_projectsPath, WepsFileChooser.OPEN);
        if(c_projectsPath != null){
            wfc.setCurrentDirectory(new File(c_projectsPath).getAbsoluteFile());
        }
        wfc.homeToolTip(wfc);

        int returnValue = wfc.showOpenDialog(this);
        if (returnValue == wfc.APPROVE_OPTION) {
            File file = new File(wfc.getSelectedFile());
            c_model.addRunFileToModel(null, file);
        }
    }

    protected void MI_exportRun_actionPerformed(java.awt.event.ActionEvent evt) {
        int rowIndex = getSelectedRow();
        if (rowIndex < c_meta.getNumHeaderRows()) {
            JOptionPane.showMessageDialog(this, "No Run Selected", Application.WMRM.getName(), JOptionPane.INFORMATION_MESSAGE);
            return;
        }
        rowIndex = c_meta.getDataRow(rowIndex) - c_meta.getNumHeaderRows();
        RunWrapper run = c_model.getRunWrapper(rowIndex);
        RunExporter exporter = new RunExporter(run.getDirectory(), null, false);
        exporter.display(this);
    }

    protected void MI_deleteRuns_actionPerformed(java.awt.event.ActionEvent evt) {
        try {
            setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
            int rowIndex = getSelectedRow();
            if (rowIndex < c_meta.getNumHeaderRows()) {
                JOptionPane.showMessageDialog(this, "No Run Selected", Application.WMRM.getName(), JOptionPane.INFORMATION_MESSAGE);
                return;
            }
            rowIndex = c_meta.getDataRow(rowIndex) - c_meta.getNumHeaderRows();
            RunWrapper run = c_model.getRunWrapper(rowIndex);
            c_weps.deleteRun(run.getDirectory());
            c_model.fireDataReset();
        }
        finally {
            setCursor(Cursor.getDefaultCursor());
        }

    }

    protected void MI_reloadRun_ActionPerformed(java.awt.event.ActionEvent event) {
        int rowIndex = getSelectedRow();
        if (rowIndex < c_meta.getNumHeaderRows()) {
            JOptionPane.showMessageDialog(this, "No Run Selected", Application.WMRM.getName(), JOptionPane.INFORMATION_MESSAGE);
            return;
        }
        rowIndex = c_meta.getDataRow(rowIndex) - c_meta.getNumHeaderRows();
        RunWrapper run = c_model.getRunWrapper(rowIndex);
        c_weps.restoreRun(run.getDirectory());
    }

    protected void MI_printAction_performed(java.awt.event.ActionEvent evt) {
        JCPrintTable pt = new JCPrintTable(LT_runs);
        PageFormat format = pt.getPageFormat();
        if (format == null) {
            format = new PageFormat();
        }
        format.setOrientation(PageFormat.LANDSCAPE);
        pt.setPageFormat(format);
        pt.showPrintPreview("Multiple Run Manager");
    }
    //Tree Events

    public void valueChanged(TreeSelectionEvent event) {
        try {
            //c_model.selectRunGroup((DataModel.RunGroup) event.getNewLeadSelectionPath().getLastPathComponent());
            DataModel.RunGroup[] groups = new DataModel.RunGroup[JTR_groups.getSelectionPaths().length];
            int i = 0;
            for (TreePath path : JTR_groups.getSelectionPaths()) {
                groups[i] = (DataModel.RunGroup) path.getLastPathComponent();
                i++;
            }
            c_model.selectRunGroups(groups);
        }
        catch (NullPointerException npe) {
        }
    }

    public void treeWillCollapse(TreeExpansionEvent event) throws ExpandVetoException {
        if (event.getPath().getLastPathComponent() == c_model.getRoot()) {
            throw new ExpandVetoException(event);
        }
    }

    public void treeWillExpand(TreeExpansionEvent event) {
    }
    //Key Events

    public void keyPressed(KeyEvent event) {
        if (event.getSource() == JTR_groups) {
            //Tree keyboard events
            if (event.getKeyCode() == 127) {
                //Pressed the delete key
                //We don't delete the root or it's direct children.
                Object selectedObject = JTR_groups.getSelectionPath().getLastPathComponent();
                if (c_model.getRoot() == selectedObject) {
                    return;
                }
                int selectedIndex = c_model.getIndexOfChild(c_model.getRoot(), selectedObject);
                if (selectedIndex >= 0) {
                    return;                //make sure the user wants to delete the node.
                }
                int result = JOptionPane.showConfirmDialog(this, "Are you sure you want to remove " + selectedObject.toString() + "?\nThis will not remove the physical file.  Only the display will be changed.", Application.WMRM.getName(), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
                if (result == JOptionPane.YES_OPTION) {
                    JTR_groups.setSelectionPath(c_model.getPathToNode(((DataModel.RunGroup) selectedObject).getParent()));
                    c_model.removeRunGroupFromModel((DataModel.RunGroup) selectedObject);
                }


            }
        }
    }

    public void keyReleased(KeyEvent event) {
    }

    public void keyTyped(KeyEvent event) {
    }
    //Window events

    protected void form_windowClosed(java.awt.event.WindowEvent evt) {
        if (c_model != null) {
            c_model.cleanup();
        }
    }
    //JCTableDataListener Events

    public void dataChanged(JCTableDataEvent e) {
        int command = e.getCommand();
        if (command == e.ADD_ROW || command == e.RESET || command == e.NUM_ROWS || command == e.REMOVE_ROW) {
            applySort();
        }
    }

    //Component events
    protected void LT_runs_componentResized(java.awt.event.ComponentEvent evt) {
        //smartColumnResize();
    }
    //Cell Resize

    public void beforeResizeCell(JCResizeCellEvent event) {
    }

    public void resizeCell(JCResizeCellEvent event) {
    }

    public void afterResizeCell(JCResizeCellEvent event) {
        if (c_ignoreCellResize) {
            return;
        }
        checkColumnSizeCache();
        int columnIndex = event.getColumn();
        if (columnIndex == JCTableEnum.NOVALUE) {
            return;
        }
        c_columnSizeCache[columnIndex] = event.getNewColumnWidth();

    }
}
