Package simtools.util

Source Code of simtools.util.TableFilter$MouseHandler

/*
* FILE_NAME : TableFilter.java
*
* Copyright (c) 2006 EADS ASTRIUM
* All rights reserved
*
*/
package simtools.util;

import java.awt.Color;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.JOptionPane;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;

/**
* Class TableFilter
* This tableModel permit to enable filtering on columns values.
*/
public class TableFilter extends AbstractTableModel {
    /**(<b>TableModel</b>) tableModel: The table model managed by this filter.*/
    private TableModel tableModel;

    /**(<b>TableModelListener</b>) tableModelListener:The listener, registered on the table model managed that will handle data modifications.*/
    private TableModelListener tableModelListener;

    /**(<b>int[]</b>) modelToView: the arrayList that contains the filtered Rows.*/
    private ArrayList modelToView;

    /**(<b>JTableHeader</b>) tableHeader: The table header.*/
    private JTableHeader tableHeader;

    /**(<b>MouseListener</b>) mouseListener: The mouse listener, to activate filter on right click.*/
    private MouseListener mouseListener;

    /**(<b>String[]</b>) filter: The current filters array, for each column.*/
    private String[] filter;

    /**(<b>Pattern[]</b>) filterPattern: The current filter patterns, for each column.*/
    private Pattern[] filterPattern;

    /**(<b>Color</b>) defaultForegroundColor:The default foreground color of the table header.*/
    private Color defaultForegroundColor;

    /**(<b>Color</b>) filteredForegroundColor: the color to use for the filtered table header.*/
    private final static Color FILTERED_FOREGROUND_COLOR = Color.BLUE;

    private boolean activeFilter;

    /**
     * Contructor TableFilter
     * <br><b>Summary:</b><br>
     * The constructor of the class TableFilter.
     * You must set a Table model using setTableModel.
     * If not you will not have datas to filter.
     */
    public TableFilter() {
        this(null);
    }

    /**
     * Contructor TableFilter
     * <br><b>Summary:</b><br>
     * The constructor of the class TableFilter.
     * @param tableModel    The tableModel to be managed.
     */
    public TableFilter(TableModel tableModel) {
        //create the modelToView data structure.
        modelToView = new ArrayList();
        //Create the listener that will handler data changes.
        tableModelListener = new TableFilterHandler();
        mouseListener = new MouseHandler();
        activeFilter = false;
        //set the tableModel
        setTableModel(tableModel);
    }

    /**
     * Method setTableModel
     * <br><b>Summary:</b><br>
     * This method sets the model that is managed by this tableFilter.
     * @param tableModel    The model to be managed by this tableFilter.
     */
    public void setTableModel(TableModel tableModel) {
        //remove this from previous table model listener, no to follow old data changes.
        if (this.tableModel != null) {
            this.tableModel.removeTableModelListener(tableModelListener);
            //nullify filters
            filter = null;
            filterPattern = null;
        }
        //then set teh table model to the one given.
        this.tableModel = tableModel;
        if (this.tableModel != null) {
            //Add the modelListener to the tableModel given.
            this.tableModel.addTableModelListener(tableModelListener);
            //create the filter.
            int nbColumns = tableModel.getColumnCount();
            filter = new String[nbColumns];
            filterPattern = new Pattern[nbColumns];
        }
        fireTableStructureChanged();
    }

    /**
     * Method updateFilteredElements
     * <br><b>Summary:</b><br>
     * This method update the filtered elements.
     */
    protected void updateFilteredElements() {
        modelToView.clear();
        //Clear the modelToView
        //We will parse all the rows of the model, and keep the one that match the filter.
        int modelRowCount = tableModel.getRowCount();
        for (int i = 0; i < modelRowCount; i++) {
            Row currentRow = new Row(i);
            if (matchFilter(currentRow)) {
                modelToView.add(currentRow);
            }
        }
        fireTableDataChanged();
    }

    /**
     * Method matchFilter
     * <br><b>Summary:</b><br>
     * This method return true if the row match the current filter.
     * @param currentRow        The row to check.
     * @return <b>(boolean)</b>  True if the given row matches the current filter.
     */
    private boolean matchFilter(Row currentRow) {
        //the result of the method.
        boolean result = true;
        //Retrieve all the row values, till found one that match.
        int index = 0;
        int columnCount = tableModel.getColumnCount();
        while (result == true && index < columnCount) {
            //TODO: make filters
            if (filterPattern[index] != null) {
                String value = tableModel.getValueAt(currentRow.modelIndex, index).toString();
                Matcher filterMatcher = filterPattern[index].matcher(value);
                result = result && filterMatcher.matches();
            }//if there is no filter, let result to true.
            //move on to next column
            index++;
        }
        //return the result
        return result;
    }

    /* (non-Javadoc)
     * @see javax.swing.table.TableModel#getColumnCount()
     */
    public int getColumnCount() {
        //The result of the method.
        int result = 0;
        if (tableModel != null) {
            result = tableModel.getColumnCount();
        }
        //return the result
        return result;
    }

    /* (non-Javadoc)
     * @see javax.swing.table.TableModel#getRowCount()
     */
    public int getRowCount() {
        //The result of the method.
        int result = 0;
        if (tableModel != null) {
            result = modelToView.size();
        }
        //return the result
        return result;
    }

    /* (non-Javadoc)
     * @see javax.swing.table.TableModel#getValueAt(int, int)
     */
    public Object getValueAt(int rowIndex, int columnIndex) {
        //the result of the method
        Object result = null;
        if (tableModel != null && modelToView != null && rowIndex < modelToView.size()) {
            Row selectedRow = (Row) modelToView.get(rowIndex);
      if(selectedRow != null){
              result = tableModel.getValueAt(selectedRow.modelIndex, columnIndex);
      }
        }
  if(result == null){
    result = "";
  }
        return result;
    }

    /**
     * Class Row
     * The class that represent a JTable row
     */
    private class Row {
        /**(<b>int</b>) modelIndex: the index of the table in the model.*/
        private int modelIndex;

        /**
         * Contructor Row
         * <br><b>Summary:</b><br>
         * The constructor of the class Row.
         * @param index The index of the row in the model
         */
        public Row(int index) {
            modelIndex = index;
        }
    }

    /* (non-Javadoc)
     * @see javax.swing.table.AbstractTableModel#getColumnName(int)
     */
    public String getColumnName(int column) {
        return tableModel.getColumnName(column);
    }

    /* (non-Javadoc)
     * @see javax.swing.table.AbstractTableModel#getColumnClass(int)
     */
    public Class getColumnClass(int column) {
        return tableModel.getColumnClass(column);
    }

    /* (non-Javadoc)
     * @see javax.swing.table.AbstractTableModel#isCellEditable(int, int)
     */
    public boolean isCellEditable(int row, int column) {
        return tableModel.isCellEditable(((Row) modelToView.get(row)).modelIndex, column);
    }

    /**
     * Method setTableHeader
     * <br><b>Summary:</b><br>
     * Permit to set the table header.
     * This way, a right click on table header will enable the filter.
     * @param tableHeader       The table header to use.
     */
    public void setTableHeader(JTableHeader tableHeader) {
        if (this.tableHeader != null) {
            //remove from previous tableHeader's mouse listener list.
            this.tableHeader.removeMouseListener(mouseListener);
            //remove the default table header color.
            defaultForegroundColor = null;
        }
        this.tableHeader = tableHeader;
        //Add in the new table header mous listener list.
        if (this.tableHeader != null) {
            this.tableHeader.addMouseListener(mouseListener);
            //retrieve the default foreground color.
            defaultForegroundColor = tableHeader.getForeground();
        }
    }

    /**
     * Method filterChanged
     * <br><b>Summary:</b><br>
     * This method is called when filter has changed.
     * It update the table.
     */
    private void filterChanged(int columnIndex) {
        //If we control a table header, change color and column value.
        if (tableHeader != null) {
            //Need to get the column that is concerned by the filter changement.
            //Because column order may have changed.
            String columnName = tableModel.getColumnName(columnIndex);
            String columnFilteredName = "*"+columnName+"*";
            Enumeration columns = tableHeader.getColumnModel().getColumns();
            TableColumn concernedColumn = null;
            while (columns.hasMoreElements()) {
                TableColumn  column = (TableColumn) columns.nextElement();
                String columnHeaderValue = (String) column.getHeaderValue();
                if (columnHeaderValue.equals(columnName) ||  columnHeaderValue.equals(columnFilteredName)){
                    concernedColumn = column;
                }
            }
            //change the header foreground with filtering status
            if (filter[columnIndex] != null && filter[columnIndex].equals("")) {
                //Set column header value to normal
                concernedColumn.setHeaderValue(columnName);
                //Check is there is at least a filter. If there is no more filter, return foreground to default.
                if (!isTableFiltered()) {
                    tableHeader.setForeground(defaultForegroundColor);
                    activeFilter = false;
                }
            } else {
                //Set column header value to filtered
                concernedColumn.setHeaderValue(columnFilteredName);
                //change the foreground color, if needed.
                if (!tableHeader.getForeground().equals(FILTERED_FOREGROUND_COLOR)) {
                    tableHeader.setForeground(FILTERED_FOREGROUND_COLOR);
                }
                activeFilter = true;
            }
            //repaint the table header, to take count of table header name changes
            tableHeader.repaint();
        }
        //Then update the filter
        String newFilter = ".*" + filter[columnIndex] + ".*";
        filterPattern[columnIndex] = Pattern.compile(newFilter);
        Thread t = new Thread(new Runnable() {
            public void run() {
                updateFilteredElements();
            }
        }, "UpdatingFilteredTableThread");
        t.start();
    }

    /**
     * Method isTableFiltered
     * <br><b>Summary:</b><br>
     * return true if there is at least an active filter.
     * @return <b>(boolean)</b>  true if there is at least an active filter.
     */
    private boolean isTableFiltered() {
        //Parse all the filters, till found a filter.
        boolean result = false;
        int index = 0;
        while (result != true && index < filter.length) {
            if (filter[index] != null && !filter[index].equals("")) {
                //If there is a non null filter, then the table is filtered, return true
                result = true;
            } else {
                //else move on the next column.
                index++;
            }
        }
        //return the result
        return result;
    }

    /**
     * Class MouseHandler
     * A mouse handler to ask fo the new filter.
     * Wake up on a right click on table header.
     */
    private class MouseHandler extends MouseAdapter {
        public void mouseClicked(MouseEvent e) {
            if (e.getButton() == MouseEvent.BUTTON3) {
                JTableHeader h = (JTableHeader) e.getSource();
                TableColumnModel columnModel = h.getColumnModel();
                int viewColumn = columnModel.getColumnIndexAtX(e.getX());
                int column = columnModel.getColumn(viewColumn).getModelIndex();
                if (column != -1) {
                    //We know we have clicked on a column.
                    //Show up a dialog to enter the new filter.
                    String newFilter = JOptionPane.showInputDialog("Enter filter for column "
                            + tableModel.getColumnName(column), filter[column]);
                    if (newFilter != null) {
                        filter[column] = newFilter;
                        filterChanged(column);
                    }
                }
            }
        }
    }

    /**
     * Class TableFilterHandler
     * This method permits to handle the table modifications that occurs.
     * It specifically handle the rowInserted event by filtering only the newly inserted elements.
     */
    private class TableFilterHandler implements TableModelListener{

        /* (non-Javadoc)
         * @see javax.swing.event.TableModelListener#tableChanged(javax.swing.event.TableModelEvent)
         */
        public void tableChanged(TableModelEvent e) {
            //If insert event, handle the inserted rows.
            if (e.getType() == TableModelEvent.INSERT){
                //get the range of rows to be processed
                int startRow = e.getFirstRow();
                int lastRow = e.getLastRow();
                //keep in mind the first index in our filtered model.
                int firstNewIndex = modelToView.size();
                //Then process the inserted rows.
                for(int i = startRow; i <= lastRow;i++){
                    Row newRow = new Row(i);
                    //If filter is not active, add the rows.
                    if(!activeFilter){
                        modelToView.add(newRow);
                    }else{
                        //Else, we have to check filter on the row.
                        if(matchFilter(newRow)){
                            modelToView.add(newRow);
                        }
                    }
                }
                //Then compute the last index.
                int lastNewIndex = modelToView.size()-1;
                //And inform the tableModelListener registered that new rows have been inserted.
                fireTableRowsInserted(firstNewIndex, lastNewIndex);
            }else{
                //If it is a more serious update of the table, update all filtered elements.
                updateFilteredElements();
            }
        }
    }
}
TOP

Related Classes of simtools.util.TableFilter$MouseHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.