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

import java.awt.Color;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Rectangle;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Random;

import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;

import de.javasoft.swing.table.ColorComboBoxTableCellEditor;
import de.javasoft.swing.table.ColorComboBoxTableCellRenderer;
import de.javasoft.swing.table.DateComboBoxTableCellEditor;
import de.javasoft.swing.table.DateComboBoxTableCellRenderer;
import de.javasoft.swing.table.FontComboBoxTableCellEditor;
import de.javasoft.swing.table.FontComboBoxTableCellRenderer;
import de.javasoft.swing.table.IntegerGroupTableCellEditor;
import de.javasoft.swing.table.IntegerGroupTableCellRenderer;
import de.javasoft.swing.table.JYComboBoxTableCellEditor;
import de.javasoft.swing.table.JYComboBoxTableCellRenderer;
import de.javasoft.swing.table.NumberTableCellEditor;
import de.javasoft.swing.table.NumberTableCellRenderer;
import de.javasoft.swing.table.SpinnerTableCellEditor;
import de.javasoft.swing.table.SpinnerTableCellRenderer;
import de.javasoft.swing.table.TextFieldTableCellEditor;

/**
 * Demonstrates usage of predefined TableCellRenderers and
 * TableCellEditors.
 */
@SuppressWarnings("serial")
public class SimpleTableCellRendererEditor extends JFrame
{
  public SimpleTableCellRendererEditor()
  {
    super("TableCellRenderer/Editor Demo");
    createAndAddComponents(getContentPane());

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

  /**
   * Create components and add them to the container.
   */
  private void createAndAddComponents(Container container)
  {
    JTable table = new JTable(new DemoModel()){
      @Override
      public void updateUI()
      {
        super.updateUI();
        //install renderer/editor in #updateUI to support LAF switch at runtime
//@highlight
        installCellRenderers(this);
        installCellEditors(this);        
//@/highlight
      }

      //to display all components properly we use a minimum row height of 19 
      @Override
      public int getRowHeight()
      {
        return Math.max(19, super.getRowHeight());
      }
    };
    
    //workaround to avoid border fallback to default scrollpane-border after a LAF switch - Java 1.5/JTable bug.
    JScrollPane scrollPane = new JScrollPane(table){
      @Override
      public void updateUI()
      {
        super.updateUI();
        setBorder(UIManager.getBorder("Table.scrollPaneBorder"));
      }
    };
    container.add(scrollPane);
  }

  private void installCellRenderers(JTable table)
  {
//@highlight
    TableCellRenderer defaultRenderer = table.getDefaultRenderer(Object.class);
    table.setDefaultRenderer(Date.class, new DateComboBoxTableCellRenderer(defaultRenderer));
    table.setDefaultRenderer(Color.class, new ColorComboBoxTableCellRenderer(defaultRenderer));
    table.setDefaultRenderer(Float.class, new SpinnerTableCellRenderer(defaultRenderer));
    table.setDefaultRenderer(Rectangle.class, new IntegerGroupTableCellRenderer(defaultRenderer));
    table.setDefaultRenderer(Integer.class, new NumberTableCellRenderer(defaultRenderer, Integer.class, 0, 0));
    table.setDefaultRenderer(ComboBoxModel.class, new JYComboBoxTableCellRenderer(defaultRenderer));    
    table.setDefaultRenderer(Font.class, new FontComboBoxTableCellRenderer(defaultRenderer));
//@/highlight
  }
  
  private void installCellEditors(JTable table)
  {
//@highlight
    TableCellEditor defaultEditor = table.getDefaultEditor(Object.class);
    table.setDefaultEditor(String.class, new TextFieldTableCellEditor(defaultEditor)); 
    table.setDefaultEditor(Date.class, new DateComboBoxTableCellEditor(defaultEditor, true, true));
    table.setDefaultEditor(Color.class, new ColorComboBoxTableCellEditor(defaultEditor, true, false, true));
    table.setDefaultEditor(Float.class, new SpinnerTableCellEditor(defaultEditor));
    table.setDefaultEditor(Rectangle.class, new IntegerGroupTableCellEditor(defaultEditor, Rectangle.class, 4));
    table.setDefaultEditor(Integer.class, new NumberTableCellEditor(defaultEditor, Integer.class, 0, 0));
    //table.setDefaultEditor(ComboBoxModel.class, new ComboBoxTableCellEditor(defaultEditor, true));
    table.setDefaultEditor(ComboBoxModel.class, new JYComboBoxTableCellEditor(defaultEditor, true, true));    
    table.setDefaultEditor(Font.class, new FontComboBoxTableCellEditor(defaultEditor, true, true));
//@/highlight

    //enable edit on doubleclick
    /*for (int i = 0; i < table.getModel().getColumnCount(); i++)
    {  
      TableCellEditor editor = table.getDefaultEditor(table.getModel().getColumnClass(i));
      if (editor instanceof AbstractTableCellEditor)
        ((AbstractTableCellEditor<?>)editor).setClicksToEdit(2);
    }*/
  }
  
  /**
   * 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");
          new SimpleTableCellRendererEditor();
        }
        catch (Exception e)
        {
          e.printStackTrace();
        }
      }
    });
  }
  
  //
  //DemoModel Class
  //
  private static class DemoModel extends AbstractTableModel 
  {
    private static Font font;
    private static ComboBoxModel cbModel = new DefaultComboBoxModel(new String[]{"Item 1", "Item 2", "Item 3", "Item 4", "Item 5"});    
    static
    {
      cbModel.setSelectedItem("Item 5");
      font = new Font("Dialog", Font.BOLD, 15);
    }
    
    private Object[][] objects = new Object[][]
    {                                              
      {"Row 1", 1.123f, new Rectangle(1,2,3,4), 90, true, createDate(), Color.RED, cbModel, font},
      {"Row 2", 2.123f, new Rectangle(11,12,13,14), 20, false, createDate(), Color.GREEN, cbModel, font},
      {"Row 3", 3.123f, new Rectangle(21,22,23,24), 70, true, createDate(), Color.BLUE, cbModel, font},
      {"Row 4", 4.444f, new Rectangle(31,32,33,34), 40, false, createDate(), Color.MAGENTA, cbModel, font},
      {"Row 5", 5.5f, new Rectangle(41,42,43,44), 10, false, createDate(), Color.ORANGE, cbModel, font},
      {"Row 6", 6.60f, new Rectangle(51,52,53,54), 60, true, createDate(), Color.LIGHT_GRAY, cbModel, font},
    };

    private Class<?>[] classes = new Class[] {String.class, Float.class, Rectangle.class, Integer.class, Boolean.class, Date.class, Color.class, ComboBoxModel. class, Font.class};

    public int getColumnCount()
    {
      return classes.length;
    }

    public int getRowCount()
    {
      return objects.length;
    }

    public String getColumnName(int column)
    {
      return getColumnClass(column).getSimpleName();
    }

    public Object getValueAt(int rowIndex, int columnIndex)
    {
      return objects[rowIndex][columnIndex];
    }

    @Override
    public void setValueAt(Object value, int row, int column)
    {
      objects[row][column] = value;
      fireTableCellUpdated(row, column);    
    }
    
//@highlight
    //return column data type to properly bind renderer/editor
    public Class<?> getColumnClass(int columnIndex)
    {
      return classes[columnIndex];
    }
//@/highlight
    
    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex)
    {
      return true;
    }
    
    private Date createDate()
    {
      Calendar cal = new GregorianCalendar();
      cal.set(Calendar.DATE, new Random().nextInt(50));
      return cal.getTime();
    }
  }  
  
}
