/* ========================
* JSynoptic : a free Synoptic editor
* ========================
*
* Project Info: http://jsynoptic.sourceforge.net/index.html
*
* This program 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;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program 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.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* (C) Copyright 2001-2005, by :
* Corporate:
* EADS Astrium SAS
* EADS CRC
* Individual:
* Claude Cazenave
*
* $Id$
*
* Changes
* -------
* 19 mai 2006 : Initial public release (CC);
*
*/
package jsynoptic.builtin.ui;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListCellRenderer;
import javax.swing.table.AbstractTableModel;
import jsynoptic.builtin.AffineTransformData;
import simtools.data.DataInfo;
import simtools.data.DataSource;
import simtools.data.DataSourcePool;
import simtools.ui.DoubleValueMapper;
import simtools.ui.FilteredSourceTree;
import simtools.ui.JPropertiesPanel;
import simtools.ui.MenuResourceBundle;
import simtools.ui.ResourceFinder;
import simtools.util.NamedProperties;
/**
* @author cazenave_c
*
*/
public class AffineTransformDataPanel extends JPropertiesPanel implements ActionListener {
static MenuResourceBundle resources = (MenuResourceBundle)ResourceFinder.get(AffineTransformDataPanel.class);
static final int ROT=0;
static final int TX=1;
static final int TY=2;
protected double[] values;
protected DataSource[] sources;
protected DoubleValueMapper[] doubleValueMappers;
DoubleValueMapper selectedDoubleMapper;
protected FilteredSourceTree dstree;
protected JCheckBox cbRotEnabled;
protected JCheckBox cbTransEnabled;
protected JCheckBox cbTransFirst;
protected TableModel tModel;
protected JTextField tfTransUnit;
protected JComboBox comboRotUnit;
protected JComboBox cbxmapper;
protected JButton beditmapper, bnewmapper, bdelmapper, bduplicatemapper;
/**
* The list of properties managed by this panel
*/
protected transient String[] _propertyNames=null;
private static final String[] defaultUnitKeys={"radian","degree",
"30deg","45deg","60deg",
"90deg","120deg","180deg"};
private static final double[] defaultUnitValues={1.,Math.PI/180.,
Math.PI/6.,Math.PI/4.,Math.PI/3,
Math.PI/2,Math.PI/1.5,Math.PI};
protected Dialog dialog;
public AffineTransformDataPanel(JDialog owner) {
super(null);
_owner = owner;
values=new double[TY+1];
sources=new DataSource[TY+1];
doubleValueMappers=new DoubleValueMapper[TY+1];
selectedDoubleMapper = null;
setLayout(new BorderLayout());
add(createUpperContent(),BorderLayout.NORTH);
add(createTable(),BorderLayout.CENTER);
JPanel lowerContent = new JPanel(new GridLayout(2,1));
lowerContent.setBorder(BorderFactory.createEtchedBorder());
lowerContent.add(createDoublevalueMapperEditionPane());
lowerContent.add(createLowerContent());
add(lowerContent,BorderLayout.SOUTH);
dstree=null;
JComponent c=createSourcePanel();
if(c!=null) add(c,BorderLayout.EAST);
dialog=null;
}
protected JComponent createUpperContent() {
Box box = Box.createHorizontalBox();
box.setBorder(BorderFactory.createEtchedBorder());
cbRotEnabled=resources.getCheckBox("cbRotEnabled",this);
box.add(cbRotEnabled);
box.add(Box.createHorizontalStrut(6));
cbTransEnabled=resources.getCheckBox("cbTransEnabled",this);
box.add(cbTransEnabled);
box.add(Box.createHorizontalStrut(6));
cbTransFirst=resources.getCheckBox("cbTransFirst",this);
box.add(cbTransFirst);
return box;
}
protected JComponent createDoublevalueMapperEditionPane(){
JPanel box = new JPanel(new FlowLayout(FlowLayout.LEFT));
box.add(new JLabel(resources.getString("useAssociation")));
cbxmapper = new JComboBox();
cbxmapper.addItem(resources.getString("=======NONE======="));
if (DoubleValueMapper.doubleValueMappers!=null)
for (int i =0; i<DoubleValueMapper.doubleValueMappers.size(); ++i) {
DoubleValueMapper tm = (DoubleValueMapper)DoubleValueMapper.doubleValueMappers.get(i);
cbxmapper.addItem(tm);
}
box.add(cbxmapper);
box.add(Box.createHorizontalGlue());
box.add(beditmapper = new JButton(resources.getString("Edit")));
box.add(bnewmapper = new JButton(resources.getString("New")));
box.add(bdelmapper = new JButton(resources.getString("Delete")));
box.add(bduplicatemapper = new JButton(resources.getString("Duplicate")));
// If "no mapper" is selected -> disable edit and del buttons
cbxmapper.setSelectedIndex(0);
beditmapper.setEnabled(false);
bdelmapper.setEnabled(false);
bduplicatemapper.setEnabled(false);
cbxmapper.setRenderer(new ListCellRenderer() {
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
String s = value.toString();
if (s.length()>18) s = s.substring(0,15) + "...";
return new JLabel(s);
}
});
beditmapper.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (selectedDoubleMapper==null) return;
selectedDoubleMapper.editDialog(AffineTransformDataPanel.this.getOwner());
cbxmapper.repaint(); // in case of name change
}
});
bnewmapper.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
selectedDoubleMapper = DoubleValueMapper.createDoubleValueMapperDialog(AffineTransformDataPanel.this.getOwner());
DoubleValueMapper.doubleValueMappers.add(selectedDoubleMapper);
cbxmapper.addItem(selectedDoubleMapper);
cbxmapper.setSelectedItem(selectedDoubleMapper);
}
});
bdelmapper.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (selectedDoubleMapper==null) return;
if (DoubleValueMapper.doubleValueMappers!=null) DoubleValueMapper.doubleValueMappers.remove(selectedDoubleMapper);
cbxmapper.removeItem(selectedDoubleMapper);
cbxmapper.setSelectedIndex(0);
for (int i =0; i<doubleValueMappers.length; ++i) {
if (doubleValueMappers[i]==selectedDoubleMapper)
doubleValueMappers[i]=null;
}
selectedDoubleMapper = null;
bdelmapper.setEnabled(false);
bduplicatemapper.setEnabled(false);
beditmapper.setEnabled(false);
}
});
bduplicatemapper.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (selectedDoubleMapper==null){
return;
}
try {
DoubleValueMapper tm = (DoubleValueMapper)((DoubleValueMapper)selectedDoubleMapper).clone();
if (DoubleValueMapper.doubleValueMappers != null) {
DoubleValueMapper.doubleValueMappers.add(tm);
}
selectedDoubleMapper = tm;
cbxmapper.addItem(selectedDoubleMapper);
cbxmapper.setSelectedItem(selectedDoubleMapper);
}catch (CloneNotSupportedException cnse){
}
}
});
cbxmapper.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int idx = cbxmapper.getSelectedIndex();
if (idx==0) {
beditmapper.setEnabled(false);
bdelmapper.setEnabled(false);
bduplicatemapper.setEnabled(false);
selectedDoubleMapper = null;
} else {
selectedDoubleMapper = (DoubleValueMapper)cbxmapper.getItemAt(idx);
beditmapper.setEnabled(true);
bdelmapper.setEnabled(true);
bduplicatemapper.setEnabled(true);
}
}
});
return box;
}
protected JComponent createLowerContent() {
JPanel box = new JPanel(new FlowLayout(FlowLayout.LEFT));
box.add(new JLabel(resources.getString("rotUnit")));
box.add(Box.createHorizontalGlue());
comboRotUnit = new JComboBox();
for(int i=0;i<defaultUnitKeys.length;i++){
comboRotUnit.addItem(resources.getString(defaultUnitKeys[i]));
}
comboRotUnit.setSelectedItem(resources.getString(defaultUnitKeys[0]));
comboRotUnit.setEditable(true);
comboRotUnit.addActionListener(this);
box.add(comboRotUnit);
box.add(Box.createHorizontalStrut(6));
box.add(new JLabel(resources.getString("transUnit")));
box.add(Box.createHorizontalGlue());
tfTransUnit=new JTextField("",5);
box.add(tfTransUnit);
return box;
}
protected JComponent createSourcePanel(){
if (DataSourcePool.global.isEmpty())
return null;
dstree = FilteredSourceTree.getFromPool("AffineTransformDataPanel");
return dstree;
}
public void updateSourcePanel(DataSource source){
dstree.setSelectedValue(source);
dstree.setEnabled(source!=null);
}
protected JComponent createTable(){
tModel=new TableModel();
JTable table=new JTable(tModel);
return table;
}
protected int parameterSize(){
return (cbRotEnabled.isSelected() ? 1 : 0)+(cbTransEnabled.isSelected() ? 2 : 0);
}
private int getMappingIndex(int rowIndex) {
switch (parameterSize()) {
case 1:
if (rowIndex != 0) {
throw new IllegalArgumentException();
}
return ROT;
case 2:
if (rowIndex != 0 && rowIndex != 1) {
throw new IllegalArgumentException();
}
return rowIndex == 0 ? TX : TY;
case 3:
if (rowIndex == 0){
return ROT;
} else if(rowIndex==1){
return TX;
} else if(rowIndex==2){
return TY;
} else{
throw new IllegalArgumentException();
}
default:
throw new IllegalArgumentException();
}
}
/* (non-Javadoc)
* @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
public void actionPerformed(ActionEvent e) {
if(e.getSource()==cbRotEnabled){
update();
}
else if(e.getSource()==cbTransEnabled){
update();
}
else if(e.getSource()==comboRotUnit){
String v=(String)comboRotUnit.getSelectedItem();
if(v!=null){
for(int i=0;i<defaultUnitKeys.length;i++){
if(v.equals(resources.getString(defaultUnitKeys[i]))){
return; // a valid utem is selected
}
}
try{
Double.parseDouble(v);
}
catch(NumberFormatException nfe){
// invalid input
comboRotUnit.setSelectedItem(resources.getString(defaultUnitKeys[0]));
}
}
}
}
/**
* Update check box enabling, table content and dialog layout
*/
protected void update(){
cbTransFirst.setEnabled(cbTransEnabled.isSelected()&&cbRotEnabled.isSelected());
comboRotUnit.setEnabled(cbRotEnabled.isSelected());
tfTransUnit.setEnabled(cbTransEnabled.isSelected());
tModel.fireTableDataChanged();
if(dialog!=null){
dialog.pack();
}
}
public class TableModel extends AbstractTableModel{
/* (non-Javadoc)
* @see javax.swing.table.TableModel#getColumnCount()
*/
public int getColumnCount() {
return 6;
}
/* (non-Javadoc)
* @see javax.swing.table.TableModel#getRowCount()
*/
public int getRowCount() {
return parameterSize();
}
/* (non-Javadoc)
* @see javax.swing.table.TableModel#getValueAt(int, int)
*/
public Object getValueAt(int rowIndex, int columnIndex) {
switch(columnIndex){
case 0:
return resources.getString("names"+getMappingIndex(rowIndex));
case 1:
return new Double(values[getMappingIndex(rowIndex)]);
case 2:
return Boolean.valueOf(sources[getMappingIndex(rowIndex)]!=null);
case 3:
DataSource ds=sources[getMappingIndex(rowIndex)];
if(ds==null){
return "";
}
return DataInfo.getLabel(ds);
case 4:
return Boolean.valueOf(doubleValueMappers[getMappingIndex(rowIndex)]!=null);
case 5:
DoubleValueMapper m=doubleValueMappers[getMappingIndex(rowIndex)];
if(m==null){
return "";
}
return m.toString();
default:
throw new IllegalArgumentException();
}
}
/* (non-Javadoc)
* @see javax.swing.table.TableModel#getColumnClass(int)
*/
public Class getColumnClass(int columnIndex){
if ((columnIndex==2)||(columnIndex==4)){
return Boolean.class;
}
return super.getColumnClass(columnIndex);
}
/* (non-Javadoc)
* @see javax.swing.table.TableModel#isCellEditable(int, int)
*/
public boolean isCellEditable(int row, int col) {
if(col==0 || col==3 || col==5){
return false;
}
if(col==2){
return dstree!=null; // no data source available
}
return true;
}
/* (non-Javadoc)
* @see javax.swing.table.TableModel#setValueAt(java.lang.Object, int, int)
*/
public void setValueAt(Object aValue, int row, int column) {
if(column==1){
values[getMappingIndex(row)]=Double.parseDouble((String)aValue);
}
else if(column==2){
if(aValue.equals(Boolean.TRUE)){
Object o= dstree.getSelectedSourceOrCollection();
if (o instanceof DataSource){
sources[getMappingIndex(row)]=(DataSource)o;
fireTableCellUpdated(row,3);
}
}else{
sources[getMappingIndex(row)]= null;
fireTableCellUpdated(row,3);
}
}else if(column==4){
if ( (aValue.equals(Boolean.TRUE)) && (selectedDoubleMapper!=null)){
doubleValueMappers[getMappingIndex(row)]=selectedDoubleMapper;
fireTableCellUpdated(row,5);
}else{
doubleValueMappers[getMappingIndex(row)]= null;
fireTableCellUpdated(row,5);
}
}
else{
throw new IllegalArgumentException();
}
}
}
static class Dialog extends JDialog{
boolean canceled;
Dialog(JDialog owner){
super(owner,true);
canceled=false;
}
}
public static NamedProperties showDialog(JDialog owner, String title, NamedProperties inputs) {
final Dialog dialog = new Dialog(owner);
dialog.setTitle(title);
AffineTransformDataPanel panel = new AffineTransformDataPanel(dialog);
panel.setProperties(inputs);
dialog.getContentPane().add(panel);
panel.dialog=dialog;
JButton cancel, ok;
JPanel p = new JPanel();
p.add(ok = new JButton(resources.getString("OK")));
p.add(cancel = new JButton(resources.getString("Cancel")));
ok.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dialog.dispose();
}
});
cancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dialog.canceled=true;
dialog.dispose();
}
});
dialog.getContentPane().add(p, BorderLayout.SOUTH);
dialog.pack();
dialog.show();
if (dialog.canceled) {
return null;
}
return panel;
}
/* (non-Javadoc)
* @see simtools.ui.JPropertiesPanel#getPropertyNames()
*/
public String[] getPropertyNames(){
if (_propertyNames==null)
_propertyNames = new AffineTransformData.AffineTransformDataPropertiesNames().getPropertyNames();
return _propertyNames;
}
/* (non-Javadoc)
* @see simtools.util.NamedProperties#getPropertyValue(java.lang.String)
*/
public Object getPropertyValue(String name) {
Object res = null;
if(name.equalsIgnoreCase("TRANS_ENABLED")) {
res = new Boolean(cbTransEnabled.isSelected());
} else if(name.equalsIgnoreCase("TX_MAPPER")) {
res = cbTransEnabled.isSelected() ? doubleValueMappers[TX] : null;
}else if(name.equalsIgnoreCase("TX_SOURCE")) {
res = cbTransEnabled.isSelected() ? sources[TX] : null;
} else if(name.equalsIgnoreCase("TY_MAPPER")) {
res = cbTransEnabled.isSelected() ? doubleValueMappers[TY] : null;
}else if(name.equalsIgnoreCase("TY_SOURCE")) {
res = cbTransEnabled.isSelected() ? sources[TY] : null;
} else if(name.equalsIgnoreCase("TX_VALUE")) {
res = cbTransEnabled.isSelected() ? new Double(values[TX]) : null;
} else if(name.equalsIgnoreCase("TY_VALUE")) {
res = cbTransEnabled.isSelected() ? new Double(values[TY]) : null;
} else if(name.equalsIgnoreCase("TRANSLATION_FIRST")) {
res = new Boolean(cbTransFirst.isSelected());
} else if(name.equalsIgnoreCase("TRANS_UNIT_SCALE")) {
try{
res=new Double(tfTransUnit.getText());
}
catch(NumberFormatException nfe){
// invalid input
res=new Double(1.);
}
} else if(name.equalsIgnoreCase("ROT_ENABLED")) {
res = new Boolean(cbRotEnabled.isSelected());
} else if (name.equalsIgnoreCase("ROT_MAPPER")) {
res = cbRotEnabled.isSelected() ? doubleValueMappers[ROT] : null;
}else if(name.equalsIgnoreCase("ROT_SOURCE")) {
res = cbRotEnabled.isSelected() ? sources[ROT] : null;
} else if(name.equalsIgnoreCase("ROT_VALUE")) {
res = cbRotEnabled.isSelected() ? new Double(values[ROT]) : null;
} else if(name.equalsIgnoreCase("ANGLE_UNIT_SCALE")) {
String v=(String)comboRotUnit.getSelectedItem();
for(int i=0;i<defaultUnitKeys.length;i++){
if(v.equals(resources.getString(defaultUnitKeys[i]))){
res=new Double(defaultUnitValues[i]); // a valid utem is selected
}
}
if(res==null){
try{
res=new Double(v);
}
catch(NumberFormatException nfe){
// invalid input
res=new Double(defaultUnitValues[0]);
}
}
}
return res;
}
/* (non-Javadoc)
* @see simtools.util.NamedProperties#setPropertyValue(java.lang.String, java.lang.Object)
*/
public void setPropertyValue(String name, Object value) {
if(name.equalsIgnoreCase("TRANS_ENABLED") && value instanceof Boolean) {
cbTransEnabled.setSelected(((Boolean)value).booleanValue());
} else if(name.equalsIgnoreCase("TX_MAPPER") && value instanceof DoubleValueMapper) {
doubleValueMappers[TX]=((DoubleValueMapper)value);
}else if(name.equalsIgnoreCase("TX_SOURCE")) {
if(value instanceof DataSource) {
sources[TX]=(DataSource)value;
updateSourcePanel((DataSource)value);
}
else sources[TX]=null;
} else if(name.equalsIgnoreCase("TY_MAPPER") && value instanceof DoubleValueMapper) {
doubleValueMappers[TY]=((DoubleValueMapper)value);
}else if(name.equalsIgnoreCase("TY_SOURCE")) {
if(value instanceof DataSource){
sources[TY]=(DataSource)value;
updateSourcePanel((DataSource)value);
}
else sources[TY]=null;
} else if(name.equalsIgnoreCase("TX_VALUE") && value instanceof Double) {
values[TX]=((Double)value).doubleValue();
} else if(name.equalsIgnoreCase("TY_VALUE")&& value instanceof Double) {
values[TY]=((Double)value).doubleValue();
} else if(name.equalsIgnoreCase("TRANSLATION_FIRST") && value instanceof Boolean) {
cbTransFirst.setSelected(((Boolean)value).booleanValue());
} else if(name.equalsIgnoreCase("TRANS_UNIT_SCALE")&& value instanceof Double) {
tfTransUnit.setText(""+((Double)value).doubleValue());
} else if(name.equalsIgnoreCase("ROT_ENABLED") && value instanceof Boolean) {
cbRotEnabled.setSelected(((Boolean)value).booleanValue());
} else if(name.equalsIgnoreCase("ROT_MAPPER") && value instanceof DoubleValueMapper) {
doubleValueMappers[ROT]=((DoubleValueMapper)value);
}else if(name.equalsIgnoreCase("ROT_SOURCE")) {
if(value instanceof DataSource) {
sources[ROT]=(DataSource)value;
updateSourcePanel((DataSource)value);
}
else sources[ROT]=null;
} else if(name.equalsIgnoreCase("ROT_VALUE")&& value instanceof Double) {
values[ROT]=((Double)value).doubleValue();
} else if(name.equalsIgnoreCase("ANGLE_UNIT_SCALE")&& value instanceof Double) {
double u=((Double)value).doubleValue();
boolean found=false;
for(int i=0;i<defaultUnitValues.length;i++){
if(u==defaultUnitValues[i]){
comboRotUnit.setSelectedItem(resources.getString(defaultUnitKeys[i])); // a valid utem is selected
found=true;
break;
}
}
if(!found){
comboRotUnit.setSelectedItem(resources.getString(defaultUnitKeys[0]));
comboRotUnit.getEditor().setItem(""+u);
}
}
}
/* (non-Javadoc)
* @see simtools.ui.JPropertiesPanel#setProperties(simtools.util.NamedProperties)
*/
public void setProperties(NamedProperties properties) {
tfTransUnit.setText("");
comboRotUnit.setSelectedItem(null);
super.setProperties(properties);
if(tfTransUnit.getText().length()==0){
tfTransUnit.setText("1.");
}
if(comboRotUnit.getSelectedItem()==null){
comboRotUnit.setSelectedItem(resources.getString(defaultUnitKeys[0]));
}
update();
}
}