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

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.Font;
import java.lang.reflect.Method;
import java.text.ParseException;

import javax.swing.JFormattedTextField.AbstractFormatter;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableCellEditor;
import javax.swing.text.DefaultFormatterFactory;

import de.javasoft.swing.JYPropertyTable;
import de.javasoft.swing.table.FormattedTextFieldTableCellEditor;
import de.javasoft.swing.table.PropertyTableModel;
import de.javasoft.swing.table.TableSeparator;

/**
 * Demonstrates integer value validation - horizontal alignment.
 */
@SuppressWarnings("serial")
public class AlignmentValidator extends JFrame
{
  private JLabel testLabel;
  
  public AlignmentValidator()
  {
    super("HorizontalAlignment Validator");
    createAndAddComponents(getContentPane());

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

  /**
   * Create components and add them to the container.
   */
  private void createAndAddComponents(final Container container)
  {
    testLabel = new JLabel("TestLabel");
    testLabel.setBorder(new EmptyBorder(10,10,10,10));    
    testLabel.setOpaque(true);
    testLabel.setBackground(new Color(0xBFFFFF));
    testLabel.setForeground(new Color(0x202020));
    testLabel.setFont(new Font("Dialog", Font.PLAIN, 20));
    container.add(testLabel, BorderLayout.NORTH);
    
    JYPropertyTable table = new JYPropertyTable();
    //add listener to update testLabel properties
    table.getModel().addTableModelListener(new ModelListener());
    initTable(table);

    //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 initTable(JYPropertyTable table)
  {
    table.addProperty("Text", testLabel.getText());
//@highlight
    Object haKey = "HorizontalAlignment";
    table.addProperty(haKey, testLabel.getHorizontalAlignment());
    table.setPropertyEditor(haKey, new HAlignmentCellEditor(table.getDefaultEditor()));
//@/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 AlignmentValidator();
        }
        catch (Exception e)
        {
          e.printStackTrace();
        }
      }
    });
  }
  
  //
  //TableListener Class to apply testLabel settings
  //
  private class ModelListener implements TableModelListener
  {      
    public void tableChanged(TableModelEvent evt)
    {
      if (evt.getColumn() == 0)
        return;
      
      int row = evt.getFirstRow();
      PropertyTableModel model = (PropertyTableModel)evt.getSource();
      Object val = model.getPropertyValue(row);

      if (val instanceof TableSeparator)
        return;

      //set value via reflection 
      try
      {
        Class<?> clazz = val.getClass();
        if (val instanceof Boolean)
          clazz = boolean.class;
        else if (val instanceof Integer)
          clazz = int.class;
        Method m = testLabel.getClass().getMethod("set"+model.getPropertyKey(row), clazz);
        m.invoke(testLabel, val);
      }
      catch (Exception e)
      {
        throw new RuntimeException(e);
      }
      
      testLabel.revalidate();
      testLabel.repaint();
    }
  }
  
  
  //
  //Horizontal Alignment TableCellEditor Class
  //
  static class HAlignmentCellEditor extends FormattedTextFieldTableCellEditor
  {
    public HAlignmentCellEditor(TableCellEditor defaultEditor)
    {
      super(defaultEditor);
      editorComponent.setHorizontalAlignment(SwingConstants.RIGHT);
      editorComponent.setFormatterFactory(new DefaultFormatterFactory(new AbstractFormatter()
      {        
        @Override
        public String valueToString(Object value) throws ParseException
        {
          if (value == null)
            return null;
          return value+"";
        }
        
        @Override
        public Object stringToValue(String text) throws ParseException
        {
          Integer align = 0;
          try
          {
            align = Integer.parseInt(text);
          }
          catch (NumberFormatException e)
          {
            throw new ParseException(e.getMessage(), -1);
          }

//@highlight
          //check for valid values: 0, 2, 4, 10, 11 
          if (align != SwingConstants.CENTER && align != SwingConstants.LEFT && align != SwingConstants.RIGHT && 
              align != SwingConstants.LEADING && align != SwingConstants.TRAILING)
          {  
            throw new ParseException("Invalid Value " + align, -1);
          }  
//@/highlight
          return align;
        }
      }));
    }    
  }  

}
