//----------------------------BEGIN LICENSE----------------------------
/* 
 * Willow : the Open Source WorkFlow Project
 * Distributable under GNU LGPL license by gun.org
 *
 * Copyright (C) 2004-2010 huihoo.org 
 * Copyright (C) 2004-2010  ZosaTapo <dertyang@hotmail.com> 
 * 
 * ====================================================================
 * Project Homepage : http://www.huihoo.org/god4j
 * Source Forge     : http://sourceforge.net/projects/huihoo
 * Mailing list     : god4j@lists.sourceforge.net 
 */
//----------------------------END  LICENSE-----------------------------
package org.huihoo.god4j.editor.panels;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Collection;
import java.util.Iterator;
import java.util.Vector;

import javax.swing.AbstractAction;
import javax.swing.Box;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;

import org.huihoo.god4j.editor.JavaDialog;
import org.huihoo.god4j.editor.XPDLCollection;
import org.huihoo.god4j.editor.XPDLComplexComponent;
import org.huihoo.god4j.editor.XPDLComponent;
/**
 * @author reic
 *
 * To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Generation - Code and Comments
 */
public class JavaTablePanel extends JavaPanel
{
	private static Dimension miniTableDimension = new Dimension(300, 75);
	private static Dimension smallTableDimension = new Dimension(400, 200);
	private static Dimension mediumTableDimension = new Dimension(600, 200);
	private static Dimension largeTableDimension = new Dimension(800, 200);

	//----------------------------------------------------------------------------
	// 为了方便访问,JTable每行第一列(index 0) 保存 XPDLComplexComponent
	//----------------------------------------------------------------------------
	protected JTable itemsTable;

	public JavaTablePanel(XPDLCollection elemCollection)
	{
		this(elemCollection, "");
	}
	public JavaTablePanel(XPDLCollection elemCollection, String title)
	{
		this(elemCollection, title, true, false);
	}
	public JavaTablePanel(XPDLCollection elemCollection, String title, boolean hasBorder, boolean automaticWidth)
	{
		this(elemCollection, title, hasBorder, automaticWidth, false);
	}
	public JavaTablePanel(
		XPDLCollection elemCollection,
		String title,
		boolean hasBorder,
		boolean automaticWidth,
		boolean miniDimension)
	{
		super(elemCollection, 2, title, JavaPanel.BOX_LAYOUT, true, hasBorder);

		// creating a table which do not allow cell editing
		Vector columnNames = new Vector();
		columnNames.add("Object");
		int columCount = 0;

		XPDLComplexComponent demoComp = elemCollection.demoComponent();
		Collection c = demoComp.findChildren();
		Iterator it = c.iterator();
		while (it.hasNext())
		{
			XPDLComponent el = (XPDLComponent) it.next();
			columnNames.add(el.getLabel());
			columCount++;
		}
		
		//System.out.println(elemCollection.getClass()+" || JavaTable : "+columCount);
		
		itemsTable = new JTable(new Vector(), columnNames)
		{
			public boolean isCellEditable(int row, int col)
			{
				return false;
			}
		};

		TableColumnModel tcm = itemsTable.getColumnModel();
		TableColumn column;
		//	setting the first column (object column) to be invisible
		column = itemsTable.getColumnModel().getColumn(0);
		column.setMinWidth(0);
		column.setMaxWidth(0);
		column.setPreferredWidth(0);
		column.setResizable(false);

		int[] invisibleIndexes = elemCollection.getInvisibleTableIndexes();
		// setting fields that will not be displayed within the table
		if (invisibleIndexes != null && invisibleIndexes.length > 0)
		{
			columCount -= invisibleIndexes.length;
			for (int i = 0; i < invisibleIndexes.length; i++)
			{
				if ((invisibleIndexes[i]+1) < itemsTable.getColumnModel().getColumnCount())
				{
					column = itemsTable.getColumnModel().getColumn(invisibleIndexes[i]+1);
					column.setMinWidth(0);
					column.setMaxWidth(0);
					column.setPreferredWidth(0);
					column.setResizable(false);
				}
			}
		}

		// setting some table properties
		itemsTable.setColumnSelectionAllowed(false);
		itemsTable.setRowSelectionAllowed(true);
		itemsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		itemsTable.getTableHeader().setReorderingAllowed(false);
		// fills Table
		DefaultTableModel dtm = (DefaultTableModel) itemsTable.getModel();
		
		it = elemCollection.getTableComponents().iterator();
		while (it.hasNext())
		{
			XPDLComplexComponent elem = (XPDLComplexComponent) it.next();
			Vector v = new Vector(elem.findChildrenValues());

			//-----------------------------------------------------------------
			// add object itself to the first column (it is invisible column)
			//-----------------------------------------------------------------
			v.add(0, elem);

			dtm.addRow(v);
		}
		// mouse listener for editing on double-click
		itemsTable.addMouseListener(new MouseAdapter()
		{
			public void mouseClicked(MouseEvent me)
			{
				if (me.getClickCount() > 1)
				{
					editElementDialog();
				}
			}
		});
		itemsTable.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false), "edit");
		itemsTable.getActionMap().put("edit", new AbstractAction()
		{
			public void actionPerformed(ActionEvent e)
			{
				editElementDialog();
			}
		});
		itemsTable.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0, false), "delete");
		itemsTable.getActionMap().put("delete", new AbstractAction()
		{
			public void actionPerformed(ActionEvent e)
			{
				deleteElementDialog();
			}
		});
		itemsTable.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false), "cancel");
		itemsTable.getActionMap().put("cancel", new AbstractAction()
		{
			public void actionPerformed(ActionEvent e)
			{
				JavaDialog d = ((JavaDialog) getDialog());
				d.setCanceled(true);
				d.dispose();
			}
		});
		// creates panel
		JScrollPane itemsTablePane = new JScrollPane();
		itemsTablePane.setViewportView(itemsTable);
		Dimension tDim;
		if (miniDimension)
		{
			tDim = new Dimension(miniTableDimension);
		}
		else if (columCount <= 3)
		{
			tDim = new Dimension(smallTableDimension);
		}
		else if (columCount <= 5)
		{
			tDim = new Dimension(mediumTableDimension);
		}
		else
		{
			tDim = new Dimension(largeTableDimension);
		}
		if (automaticWidth)
		{
			tDim.width = itemsTable.getPreferredScrollableViewportSize().width;
		}
		itemsTable.setPreferredScrollableViewportSize(new Dimension(tDim));
		add(itemsTablePane);
		add(Box.createVerticalGlue());
	}

	public JTable getTable()
	{
		return itemsTable;
	}

	public XPDLComplexComponent getSelectedElement()
	{
		JTable t = getTable();
		int row = t.getSelectedRow();
		if (row >= 0)
		{
			return (XPDLComplexComponent) t.getValueAt(row, 0);
		}
		return null;
	}
	public void modifyElement(XPDLComplexComponent e)
	{
		JTable t = getTable();
		int row = t.getSelectedRow();
		DefaultTableModel dtm = (DefaultTableModel) t.getModel();
		Vector v = new Vector(((XPDLComplexComponent) e).findChildrenValues());

		//-----------------------------------------------------------------
		// add object itself to the first column (it is invisible column)
		//-----------------------------------------------------------------
		v.add(0, e);

		dtm.removeRow(row);
		dtm.insertRow(row, v);
		try
		{
			t.setRowSelectionInterval(row, row);
		}
		catch (Exception ex)
		{
		}
	}
	public void removeElement(XPDLComplexComponent e)
	{
		((XPDLCollection) getXPDLComponent()).removeComponent(getSelectedElement());
		JTable t = getTable();
		int row = t.getSelectedRow();
		DefaultTableModel dtm = (DefaultTableModel) t.getModel();
		dtm.removeRow(row);
		try
		{
			if (row == 0)
			{
				row++;
			}
			t.setRowSelectionInterval(row - 1, row - 1);
		}
		catch (Exception ex)
		{
		}
		t.requestFocus();
	}
	private void editElementDialog()
	{
		XPDLComplexComponent editElement = getSelectedElement();
		if (editElement != null)
		{
			JavaDialog de =
				new JavaDialog(
					getDialog(),
					editElement.getLabel() + " '" + editElement.toString() + "' - " + sm.getString("EditingKey"));
			de.editXPDLComponent(editElement.getJavaPanel(), true, false);
			if (!de.isCanceled())
			{
				modifyElement(editElement);
				((XPDLCollection) getXPDLComponent()).onElementModified(editElement);
			}
		}
		else
		{
			JOptionPane.showMessageDialog(
				getDialog(),
				sm.getString("WarningEmptySelectionToEditOrDelete"),
				sm.getString("Title"),
				JOptionPane.WARNING_MESSAGE);
		}
		getTable().requestFocus();
	}
	private void deleteElementDialog()
	{
		XPDLComplexComponent deleteElement = getSelectedElement();
		if (deleteElement == null)
		{
			JOptionPane.showMessageDialog(
				getDialog(),
				sm.getString("WarningEmptySelectionToEditOrDelete"),
				sm.getString("Title"),
				JOptionPane.WARNING_MESSAGE);
		}
		else if (deleteElement.isReadOnly())
		{
			JOptionPane.showMessageDialog(
				getDialog(),
				sm.getString(((XPDLCollection) getXPDLComponent()).getReadOnlyMessageName(deleteElement)),
				sm.getString("Title"),
				JOptionPane.WARNING_MESSAGE);
		}
		else if (!((XPDLCollection) getXPDLComponent()).canRemoveElement(deleteElement))
		{
			JOptionPane.showMessageDialog(
				getDialog(),
				sm.getString(((XPDLCollection) getXPDLComponent()).getInUseMessageName(deleteElement)),
				sm.getString("Title"),
				JOptionPane.WARNING_MESSAGE);
		}
		else
		{
			int yn =
				JOptionPane.showConfirmDialog(
					getDialog(),
					sm.getString("MessageDoYouReallyWantToRemoveSelectedItem"),
					deleteElement.getLabel() + " - " + sm.getString("DeletingKey"),
					JOptionPane.YES_NO_OPTION);
			if (yn == JOptionPane.YES_OPTION)
			{
				removeElement(deleteElement);
				((XPDLCollection) getXPDLComponent()).onElementDeleted(deleteElement);
			}
		}
	}
}