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

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Date;

import javax.swing.DefaultBoundedRangeModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SpinnerNumberModel;
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.HyperlinkTableCellRenderer;
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.ObjectTableCellEditor;
import de.javasoft.swing.table.ObjectTableCellRenderer;
import de.javasoft.swing.table.SeparatorTableCellRenderer;
import de.javasoft.swing.table.SliderTableCellEditor;
import de.javasoft.swing.table.SliderTableCellRenderer;
import de.javasoft.swing.table.SpinnerTableCellEditor;
import de.javasoft.swing.table.SpinnerTableCellRenderer;
import de.javasoft.swing.table.TableSeparator;
import de.javasoft.swing.table.TextFieldTableCellEditor;
import de.javasoft.swing.table.UneditableTableCellEditor;

/**
 * Demonstrates usage of predefined TableCellRenderers and
 * TableCellEditors.
 */
@SuppressWarnings("serial")
public class AllTableCellRenderersEditors extends JFrame
{
  public AllTableCellRenderersEditors()
  {
    super("TableCellRenderer/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(Boolean.class, new CheckBoxTableCellRenderer(defaultRenderer));
    renderer.addRenderer(Integer.class, new NumberTableCellRenderer(defaultRenderer, Integer.class, 0, 0));
    renderer.addRenderer(Dimension.class, new IntegerGroupTableCellRenderer(defaultRenderer));
    
    HyperlinkTableCellRenderer urlRenderer = new HyperlinkTableCellRenderer(defaultRenderer);
    table.addMouseListener(urlRenderer);
    table.addMouseMotionListener(urlRenderer);
    renderer.addRenderer(URL.class, urlRenderer);
    
    renderer.addRenderer(TableSeparator.class, new SeparatorTableCellRenderer(defaultRenderer));
    renderer.addRenderer(SpinnerNumberModel.class, new SpinnerTableCellRenderer(defaultRenderer));
    renderer.addRenderer(DefaultBoundedRangeModel.class, new SliderTableCellRenderer(defaultRenderer));
    //renderer.addRenderer(ComboBoxModel.class, new ComboBoxTableCellRenderer(defaultRenderer));
    renderer.addRenderer(DefaultComboBoxModel.class, new JYComboBoxTableCellRenderer(defaultRenderer));    
    renderer.addRenderer(Color.class, new ColorComboBoxTableCellRenderer(defaultRenderer));
    renderer.addRenderer(Date.class, new DateComboBoxTableCellRenderer(defaultRenderer));
    renderer.addRenderer(Font.class, new FontComboBoxTableCellRenderer(defaultRenderer));
//@/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(Boolean.class, new CheckBoxTableCellEditor(defaultEditor));
    editor.addEditor(Integer.class, new NumberTableCellEditor(defaultEditor, Integer.class, 0, 0));
    editor.addEditor(Dimension.class, new IntegerGroupTableCellEditor(defaultEditor, Dimension.class, 2));
    editor.addEditor(URL.class, new UneditableTableCellEditor(defaultEditor));
    editor.addEditor(TableSeparator.class, new UneditableTableCellEditor(defaultEditor));    
    editor.addEditor(SpinnerNumberModel.class, new SpinnerTableCellEditor(defaultEditor));    
    editor.addEditor(DefaultBoundedRangeModel.class, new SliderTableCellEditor(defaultEditor));    
    
    boolean editableField = true;
    //editor.addEditor(ComboBoxModel.class, new ComboBoxTableCellEditor(defaultEditor, editableField));
    editor.addEditor(DefaultComboBoxModel.class, new JYComboBoxTableCellEditor(defaultEditor, editableField, false));       
    editor.addEditor(Date.class, new DateComboBoxTableCellEditor(defaultEditor, editableField, false));
    editor.addEditor(Color.class, new ColorComboBoxTableCellEditor(defaultEditor, editableField, false, false));
    editor.addEditor(Font.class, new FontComboBoxTableCellEditor(defaultEditor, editableField, false));
//@/highlight

    //enable edit on doubleclick
    //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 AllTableCellRenderersEditors();
        }
        catch (Exception e)
        {
          e.printStackTrace();
        }
      }
    });
  }
  
  //
  //DemoModel Class
  //
  private static class DemoModel extends AbstractTableModel 
  {
    private static URL url;
    private static TableSeparator separator = new TableSeparator();
    static
    {
      try
      {
        url = new URL("http://www.jyloo.com");
      }
      catch (MalformedURLException e)
      {
        e.printStackTrace();
      }
    }
    
    private Object[][] objects = new Object[][]
    {                                              
      {"TextFieldTableCellEditor", "TextField"},
      //{"FormattedTextFieldTableCellEditor", "FormattedTextField"},
      {"BooleanTableCellRenderer/Editor", true},
      {"NumberTableCellRenderer/Editor", 1234567890},
      {"IntegerGroupTableCellRenderer/Editor", new Dimension(10,20)},
      {"URL", url},
      {separator, separator},
      {"SpinnerTableCellRenderer/Editor", new SpinnerNumberModel(50, -100, 100, 10)},
      {"SliderTableCellRenderer/Editor", new DefaultBoundedRangeModel(50, 1, 0, 100)},
      {separator, separator},
      {"JYComboBoxTableCellRenderer/Editor", new DefaultComboBoxModel(new String[]{"Item 1", "Item 2", "Item 3", "Item 4", "Item 5"})},
      {"DateTableCellRenderer/Editor", new Date()},
      {"ColorTableCellRenderer/Editor", Color.RED},
      {"FontTableCellRenderer/Editor", new Font("Dialog", Font.BOLD, 15)},
    };

    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;
    }    
  }  
  
}
