package de.javasoft.synthetica.democenter.examples.jytable;

import java.awt.Container;
import java.awt.EventQueue;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.RowFilter;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;

import org.jdesktop.swingx.sort.RowFilters.GeneralFilter;
import org.jdesktop.swingx.table.TableColumnExt;

import de.javasoft.swing.JYTable;
import de.javasoft.swing.JYTableHeader;
import de.javasoft.swing.JYTableScrollPane;
import de.javasoft.swing.filter.ColumnFilterFactories.PatternColumnFilterFactory;
import de.javasoft.swing.filter.IColumnFilterFactory;
import de.javasoft.swing.filter.IRowFilterModel;
import de.javasoft.swing.filter.IRowFilterModelFactory;
import de.javasoft.swing.filter.PatternRowFilterModel;
import de.javasoft.swing.jytable.JYTableColumnExt;
import de.javasoft.swing.jytable.renderer.CellLayoutHint;
import de.javasoft.swing.sort.RowFilters;

/**
 * Demonstrates how to add a custom filter.
 */
@SuppressWarnings("serial")
public class CustomTextFilter extends JFrame
{
  public CustomTextFilter()
  {
    super("Custom Table Filters");
    createAndAddComponents(getContentPane());

    //setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);      
    setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    setSize(700,300);
    setLocationRelativeTo(null);
    setVisible(true);
  }

  /**
   * Create components and add them to the container.
   */
  private void createAndAddComponents(Container container)
  {
    String[] columnNames = {"First Name", "Last Name", "Sport", "# of Years", "Active", "Best run time"};
    Object[][] data = { 
                        {"Kathy", "Smith", "Snowboarding", 5, false, 58000},
                        {"John", "Doe", "Walking", 3, true, 68000}, 
                        {"Sue", "Black", "Jogging", 2, false, 61000},
                        {"Jane", "White", "Speed reading", 20, false, 120000}, 
                        {"Joe", "Brown", "Climbing", 10, true, 65000},
                        {"Peter", "Parker", "Broad jumping", 3, true, 52000}, 
                      };
    final Class<?>[] columnClasses = {String.class, String.class, String.class, Integer.class, Boolean.class, Integer.class}; 

    DefaultTableModel model = new DefaultTableModel(data, columnNames)
    {
      @Override
      public Class<?> getColumnClass(int columnIndex)
      {
        return columnClasses[columnIndex];
      }
    };
    JYTable table = new JYTable(model);

//@highlight
    //add "not starts with" filter and set as initial filter
    IRowFilterModelFactory<TableModel> customRowFilterModelFactory = new IRowFilterModelFactory<TableModel>() 
    {
      public IRowFilterModel<TableModel> createRowFilterModel(int columnIndex) 
      {
        return new CustomRowFilterModel<TableModel>(columnIndex);
      }      
    };
    //use PatternColumnFilterFactory for String type
    IColumnFilterFactory<TableModel> customFilterColumnFactory = new PatternColumnFilterFactory<TableModel>(customRowFilterModelFactory);
    ((JYTableColumnExt) table.getColumn(0)).setColumnFilterFactory(customFilterColumnFactory);
//@/highlight

//@highlight
    //set initial filter for Years column to AFTER_EQUAL and value to 3
    TableColumnExt col = table.getColumnExt(3);
    table.getFilterRowController().getColumnFilter(col).getRowFilterModel().setMatchValue(3);
    table.getFilterRowController().getColumnFilter(col).getRowFilterModel().setMatchRule(RowFilters.ComparisonTypeExt.AFTER_EQUAL);
//@/highlight
    
    JYTableHeader header =  (JYTableHeader)table.getTableHeader();
    CellLayoutHint hint = header.getCellLayoutHint();
    //center header text
    header.setCellLayoutHint(new CellLayoutHint(hint.sortMarkerPosition, SwingConstants.CENTER, hint.verticalAlignment));
    //use a JYTableScrollPane for the filter row
    JYTableScrollPane scrollPane = new JYTableScrollPane(table);
    container.add(scrollPane);    
  }
  
  /**
   * Static main method for application startup. 
   */
  public static void main(String[] args)
  {
    EventQueue.invokeLater(new Runnable()
    {
      public void run()
      {
        try
        {
          UIManager.setLookAndFeel("de.javasoft.plaf.synthetica.SyntheticaStandardLookAndFeel");
//@highlight
          // primitive localize (add to custom properties)
          UIManager.put("NOT_STARTS_WITH", "not beginning with");
//@/highlight
          new CustomTextFilter();
        }
        catch (Exception e)
        {
          e.printStackTrace();
        }
      }
    });
  }
  
  //
  //Custom filter model for match rule "not starts with"
  //
  
  //for strings extend PatternRowFilterModel - for numbers extend ComparableRowFilterModel
  private static class CustomRowFilterModel<M> extends PatternRowFilterModel<M>
  {
    //text mapping also supported by UI-property defaults
    private static String customRule = "NOT_STARTS_WITH";

    public CustomRowFilterModel(int columnIndex)
    {
      //pass rule to set as initial rule in popup
      super(columnIndex, customRule);
    }

    @Override
    protected RowFilter<? super M, ? super Integer> createRowFilter()
    {
      if (getMatchRule() == customRule) 
        return createMyRowFilter();
      return super.createRowFilter();
    }

    private RowFilter<? super M, ? super Integer> createMyRowFilter()
    {
      //negate for numbers 
      return (getMatchValue() instanceof Number) ? null : new CustomRowFilter((String) getMatchValue(), getColumnIndex());
    }

    @Override
    public List<String> getMatchRules()
    {
      List<String> matchRules = new ArrayList<String>(super.getMatchRules());
      matchRules.add(customRule);
      return matchRules;
    }
  }

  //
  // Custom row filter
  //
  private static class CustomRowFilter extends GeneralFilter
  {
    private String matchValue;

    public CustomRowFilter(String s, int... columns)
    {
      super(columns);
      this.matchValue = s;
    }

//@highlight
    //the match rule implementation
    @Override
    protected boolean include(javax.swing.RowFilter.Entry<? extends Object, ? extends Object> entry, int index)
    {
      String value = ((String) entry.getValue(index)).toLowerCase();
      return matchValue == null || matchValue.trim().length() == 0 ? true : !value.startsWith(matchValue.toLowerCase());
    }
//@/highlight
  }
  
}
