/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2012-2013, Geomatys
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotoolkit.gui.swing.etl;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.tree.DefaultMutableTreeNode;
import org.geotoolkit.gui.swing.util.ActionCell;
import org.geotoolkit.gui.swing.resource.IconBundle;
import org.geotoolkit.gui.swing.resource.MessageBundle;
import org.geotoolkit.processing.chain.model.ChainDataTypes;
import org.geotoolkit.processing.chain.model.Parameter;
import org.geotoolkit.processing.chain.model.Parameterized;
import org.geotoolkit.processing.chain.model.event.ChainListener;
import org.geotoolkit.processing.chain.model.event.EventChain;
import org.geotoolkit.gui.swing.util.SwingUtilities;
import org.geotoolkit.util.collection.CollectionChangeEvent;
import org.jdesktop.swingx.JXTable;
/**
* Edition panel for Chain input and output parameters.
*
* @author Johann Sorel (Geomatys)
*/
public class JChainParametersPanel extends JPanel{
private static final ImageIcon ICON_EDIT = IconBundle.getIcon("16_edit_geom");
private static final ImageIcon ICON_DELETE = IconBundle.getIcon("16_remove");
private final boolean editableInput;
private final boolean editableOutput;
/**
* Currently edited chain.
*/
private final Parameterized process;
public JChainParametersPanel(final Parameterized process, final boolean editableInput, final boolean editableOutput) {
super(new GridLayout(2,1));
this.process = process;
this.editableInput = editableInput;
this.editableOutput = editableOutput;
add(createPanel(true));
add(createPanel(false));
setPreferredSize(new Dimension(300, 300));
}
private JPanel createPanel(final boolean in){
final boolean editable = in ? editableInput : editableOutput;
final JPanel guiTopPanel = new JPanel(new FlowLayout());
final JPanel guiPanel = new JPanel(new BorderLayout());
final JLabel guiLabel = new JLabel(
MessageBundle.format(in ? "chainInputs" : "chainOutputs"));
guiLabel.setBorder(BorderFactory.createEmptyBorder(6, 4, 6, 4));
guiTopPanel.add(guiLabel);
final ParametersTableModel model;
if(process instanceof EventChain) {
final EventChain chain = (EventChain) process;
model = new ChainParametersTableModel(chain, in, editable);
} else {
model = new ParametersTableModel(process, in, editable);
}
if (editable) {
final JButton guiAdd = new JButton(IconBundle.getIcon("16_add"));
guiAdd.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(in){
process.getInputs().add(new Parameter(nextInCode(),
ChainDataTypes.VALID_TYPES.get(0), "", 1, 1));
}else{
process.getOutputs().add(new Parameter(nextOutCode(),
ChainDataTypes.VALID_TYPES.get(0), "", 1, 1));
}
model.fireTableDataChanged();
}
});
guiTopPanel.add(guiAdd);
}
final ActionCell.Renderer cellRendererEdit = new ActionCell.Renderer(ICON_EDIT){
@Override
public Icon getIcon(Object value) {
if(value instanceof DefaultMutableTreeNode){
value = ((DefaultMutableTreeNode)value).getUserObject();
}
if(value instanceof Parameter){
final Parameter parameter = (Parameter) value;
return super.getIcon(value);
}
return null;
}
};
final ActionCell.Renderer cellRendererRemove = new ActionCell.Renderer(ICON_DELETE){
@Override
public Icon getIcon(Object value) {
if(value instanceof DefaultMutableTreeNode){
value = ((DefaultMutableTreeNode)value).getUserObject();
}
if(value instanceof Parameter){
final Parameter parameter = (Parameter) value;
return super.getIcon(value);
}
return null;
}
};
final ActionCell.Editor cellEditEdit = new ActionCell.Editor(ICON_EDIT){
@Override
public void actionPerformed(ActionEvent e, Object value) {
if(value instanceof DefaultMutableTreeNode){
value = ((DefaultMutableTreeNode)value).getUserObject();
}
final Parameter parameter;
if(value instanceof Parameter){
parameter = (Parameter) value;
}else{
return;
}
//show edit dialog
JParameterPanel.showDialog(JChainParametersPanel.this, process,parameter, (in) ? Integer.MIN_VALUE : Integer.MAX_VALUE, in, editable);
model.fireTableDataChanged();
}
@Override
public Icon getIcon(Object value) {
if(value instanceof DefaultMutableTreeNode){
value = ((DefaultMutableTreeNode)value).getUserObject();
}
if(value instanceof Parameter){
final Parameter parameter = (Parameter) value;
return super.getIcon(value);
}
return null;
}
};
final ActionCell.Editor cellEditRemove = new ActionCell.Editor(ICON_DELETE){
@Override
public void actionPerformed(ActionEvent e, Object value) {
if(value instanceof DefaultMutableTreeNode){
value = ((DefaultMutableTreeNode)value).getUserObject();
}
final Parameter parameter;
if(value instanceof Parameter){
parameter = (Parameter) value;
}else{
return;
}
//delete parameter
if(in){
process.getInputs().remove(parameter);
}else{
process.getOutputs().remove(parameter);
}
model.fireTableDataChanged();
}
@Override
public Icon getIcon(Object value) {
if(value instanceof DefaultMutableTreeNode){
value = ((DefaultMutableTreeNode)value).getUserObject();
}
if(value instanceof Parameter){
final Parameter parameter = (Parameter) value;
return super.getIcon(value);
}
return null;
}
};
final JXTable guiTable = new JXTable(){
@Override
public TableCellEditor getCellEditor(int row, int column) {
if(column==1){
return cellEditEdit;
}else if(column==2){
return cellEditRemove;
}
return super.getCellEditor(row, column);
}
@Override
public TableCellRenderer getCellRenderer(int row, int column) {
if(column==1){
return cellRendererEdit;
}else if(column==2){
return cellRendererRemove;
}
return super.getCellRenderer(row, column);
}
};
guiTable.setModel(model);
guiTable.setTableHeader(null);
guiTable.getColumnModel().getColumn(1).setPreferredWidth(40);
guiTable.getColumnModel().getColumn(1).setMinWidth(40);
guiTable.getColumnModel().getColumn(1).setWidth(40);
guiTable.getColumnModel().getColumn(1).setMaxWidth(40);
guiTable.getColumnModel().getColumn(1).setResizable(false);
if (guiTable.getColumnModel().getColumnCount() > 2) {
guiTable.getColumnModel().getColumn(2).setPreferredWidth(40);
guiTable.getColumnModel().getColumn(2).setMinWidth(40);
guiTable.getColumnModel().getColumn(2).setMaxWidth(40);
guiTable.getColumnModel().getColumn(2).setWidth(40);
guiTable.getColumnModel().getColumn(2).setResizable(false);
}
guiTable.setDefaultRenderer(Parameter.class, new DefaultTableCellRenderer(){
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
final JLabel lbl = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
lbl.setIcon(null);
if(value instanceof Parameter){
final Parameter param = (Parameter) value;
lbl.setText(param.getCode());
}
return lbl;
}
});
guiPanel.add(BorderLayout.NORTH, guiTopPanel);
guiPanel.add(BorderLayout.CENTER, new JScrollPane(guiTable));
return guiPanel;
}
/**
* Generate next unused input parameter code.
*/
private String nextInCode(){
int i=1;
incloop:
for(;;i++){
for(final Parameter param : process.getInputs()){
if( ("in"+i).equalsIgnoreCase(param.getCode())){
continue incloop;
}
}
break incloop;
}
return "in"+i;
}
/**
* Generate next unused output parameter code.
*/
private String nextOutCode(){
int i=1;
incloop:
for(;;i++){
for(final Parameter param : process.getOutputs()){
if( ("out"+i).equalsIgnoreCase(param.getCode())){
continue incloop;
}
}
break incloop;
}
return "out"+i;
}
private class ChainParametersTableModel extends ParametersTableModel implements ChainListener{
public ChainParametersTableModel(final EventChain chain,final boolean in, final boolean editable) {
super(chain, in, editable);
chain.addListener(this);
}
private void updateModel(){
fireTableDataChanged();
}
@Override
public void constantChange(CollectionChangeEvent event) {
}
@Override
public void descriptorChange(CollectionChangeEvent event) {
}
@Override
public void linkChange(CollectionChangeEvent event) {
}
@Override
public void executionLinkChange(CollectionChangeEvent event) {
}
@Override
public void inputChange(CollectionChangeEvent event) {
if(!in) {return;}
updateModel();
}
@Override
public void outputChange(CollectionChangeEvent event) {
if(in) {return;}
updateModel();
}
}
/**
* Open JDialog of editor.
*/
public void showDialog() {
final JOptionPane optPane = new JOptionPane(this,
JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION);
final Window frame = SwingUtilities.windowForComponent(this);
final JDialog optionPaneDialog = new JDialog(frame);
optPane.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent e) {
if (e.getPropertyName().equals("value")) {
optionPaneDialog.dispose();
}
}
});
optionPaneDialog.setTitle("");
optionPaneDialog.setContentPane(optPane);
optionPaneDialog.pack();
optionPaneDialog.setResizable(true);
optionPaneDialog.setLocationRelativeTo(null);
optionPaneDialog.setModal(true);
optionPaneDialog.setVisible(true);
}
}