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.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.CheckBoxTableCellEditor;
import de.javasoft.swing.table.CheckBoxTableCellRenderer;
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.NumberTableCellEditor;
import de.javasoft.swing.table.NumberTableCellRenderer;
import de.javasoft.swing.table.ObjectTableCellEditor;
import de.javasoft.swing.table.ObjectTableCellRenderer;
import de.javasoft.swing.table.TextFieldTableCellEditor;

/**
 * Demonstrates data type related cell rendering and
 * editing.
 */
@SuppressWarnings("serial")
public class DataTypeCellRendererEditor extends JFrame
{
  public DataTypeCellRendererEditor()
  {
    super("Data Type Renderer/Editor Demo");
    createAndAddComponents(getContentPane());

    //setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);      
    setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    setSize(500,400);
    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);
    ObjectTableCellRenderer renderer = new ObjectTableCellRenderer(defaultRenderer);
    table.setDefaultRenderer(Object.class, renderer);

    //register additional renderers to object renderer
    renderer.addRenderer(Date.class, new DateComboBoxTableCellRenderer(defaultRenderer));
    renderer.addRenderer(Color.class, new ColorComboBoxTableCellRenderer(defaultRenderer));
    renderer.addRenderer(Font.class, new FontComboBoxTableCellRenderer(defaultRenderer));
    renderer.addRenderer(Rectangle.class, new IntegerGroupTableCellRenderer(defaultRenderer));
    renderer.addRenderer(Boolean.class, new CheckBoxTableCellRenderer(defaultRenderer));
    renderer.addRenderer(Integer.class, new NumberTableCellRenderer(defaultRenderer, Integer.class, 0, 0));
    renderer.addRenderer(Float.class, new NumberTableCellRenderer(defaultRenderer, Float.class, 2, 2));
    renderer.addRenderer(Double.class, new NumberTableCellRenderer(defaultRenderer, Double.class, 2, 5));
//@/highlight
  }
  
  private void installCellEditors(JTable table)
  {
//@highlight
    TableCellEditor defaultEditor = table.getDefaultEditor(Object.class);
    ObjectTableCellEditor editor = new ObjectTableCellEditor(defaultEditor);    
    table.setDefaultEditor(Object.class, editor);
    
    //register additional editors to object editor
    editor.addEditor(String.class, new TextFieldTableCellEditor(defaultEditor)); 
    editor.addEditor(Date.class, new DateComboBoxTableCellEditor(defaultEditor, true, false));
    editor.addEditor(Color.class, new ColorComboBoxTableCellEditor(defaultEditor, true, false, false));
    editor.addEditor(Font.class, new FontComboBoxTableCellEditor(defaultEditor, true, false));
    editor.addEditor(Rectangle.class, new IntegerGroupTableCellEditor(defaultEditor, Rectangle.class, 4));
    editor.addEditor(Boolean.class, new CheckBoxTableCellEditor(defaultEditor));
    editor.addEditor(Integer.class, new NumberTableCellEditor(defaultEditor, Integer.class, 0, 0));
    editor.addEditor(Float.class, new NumberTableCellEditor(defaultEditor, Float.class, 2, 2));
    editor.addEditor(Double.class, new NumberTableCellEditor(defaultEditor, Double.class, 2, 5));

    //enable edit on doubleclick
    //editor.setClicksToEdit(2);
//@/highlight
  }  
  
  /**
   * 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 DataTypeCellRendererEditor();
        }
        catch (Exception e)
        {
          e.printStackTrace();
        }
      }
    });
  }
  
  //
  //DemoModel Class
  //
  private static class DemoModel extends AbstractTableModel 
  {
    private Object[][] objects = new Object[][]
    {                                              
      {"String", "First Row", 1234567890},
      {"Color", Color.RED, new Font("Monospaced", Font.PLAIN, 12)},
      {"Date1", createDate(), 123.45f},
      {"Date2", createDate(), 1999.1234d},
      {"Font", new Font("Dialog", Font.BOLD, 15), new Rectangle(10,20,30,40)},
      {"Boolean1", false, true},
      {"Boolean2", true, false},
      {createDate(), createDate(), Color.ORANGE},
    };

    public int getColumnCount()
    {
      return objects[0].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
    public Class<?> getColumnClass(int columnIndex)
    {
      return Object.class;
    }
//@/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();
    }
  }  
  
}
