//--------------------------------------------------------------------------------//
// COPYRIGHT NOTICE //
//--------------------------------------------------------------------------------//
// Copyright (c) 2012, Instituto de Microelectronica de Sevilla (IMSE-CNM) //
// //
// All rights reserved. //
// //
// Redistribution and use in source and binary forms, with or without //
// modification, are permitted provided that the following conditions are met: //
// //
// * Redistributions of source code must retain the above copyright notice, //
// this list of conditions and the following disclaimer. //
// //
// * Redistributions in binary form must reproduce the above copyright //
// notice, this list of conditions and the following disclaimer in the //
// documentation and/or other materials provided with the distribution. //
// //
// * Neither the name of the IMSE-CNM nor the names of its contributors may //
// be used to endorse or promote products derived from this software //
// without specific prior written permission. //
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" //
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE //
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE //
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE //
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL //
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR //
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER //
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, //
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE //
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //
//--------------------------------------------------------------------------------//
package xfuzzy.xfedit;
import xfuzzy.lang.*;
import xfuzzy.util.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Vector;
/**
* Ventana de edici�n de una familia de funciones de pertenencia
* @author Francisco Jos� Moreno Velo
*
*/
public class XfeditFamilyEditor extends JDialog implements ActionListener,
ListCellRenderer, ItemListener {
/**
* C�digo asociado a la clase serializable
*/
private static final long serialVersionUID = 95505666603022L;
//----------------------------------------------------------------------------//
// MIEMBROS PRIVADOS //
//----------------------------------------------------------------------------//
/**
* Lista de campos para introducir los valores de los par�metros
*/
private XTextForm[] paramform;
/**
* Campo para introducir el nombre de la familia
*/
private XTextForm labelform;
/**
* Panel que contiene los campos de los par�metros
*/
private Box parambox;
/**
* Men� desplegable para seleccionar la familia
*/
private XComboBox functionform;
/**
* Panel para representar gr�ficamente las MF de la familia
*/
private XfeditFamilyGraphPanel graph;
/**
* Editor de tipos que realiza la llamada a XfeditFamilyEditor
*/
private XfeditTypeEditor editor;
/**
* Objeto original que describe la familia a editar
*/
private Family famorig;
/**
* Copia de trabajo sobre la que se realizan los cambios
* de edici�n de la familia
*/
private Family famcopy;
/**
* Objeto Type al que pertenece la familia
*/
private Type type;
/**
* Indice del campo que permite crear un nuevo par�metro
*/
private int index;
/**
* M�nimo n�mero de campos de par�metros
*/
private int MINSIZE = 5;
//----------------------------------------------------------------------------//
// CONSTRUCTOR //
//----------------------------------------------------------------------------//
/**
* Constructor
*/
public XfeditFamilyEditor(XfeditTypeEditor editor, Family family) {
super(editor.getXfedit(),"Xfedit",true);
this.editor = editor;
this.type = editor.getWorkingCopy();
this.famorig = family;
this.famcopy = (family == null? null : (Family) family.clone(type) );
build();
setList();
setData();
}
//----------------------------------------------------------------------------//
// M�TODOS P�BLICOS //
//----------------------------------------------------------------------------//
/**
* Interfaz ActionListener
*/
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if(command.equals("Set")) { set(); return; }
else if(command.equals("Refresh")) { if(getData()) setData(); return; }
else if(command.equals("Cancel")) { setVisible(false); return; }
int i = Integer.parseInt(command);
if(i > index ) return;
if(i == index ) addParameter();
else removeParameter(i);
}
/**
* Interfaz ListCellRenderer
*/
public Component getListCellRendererComponent(
JList list, Object value, int listindex,
boolean isSelected, boolean cellHasFocus) {
String label = "";
if(listindex == -1 && famcopy!=null) {
label = famcopy.getPackageName()+"."+famcopy.getFunctionName();
}
else if(listindex == -1) label = " ";
else label = value.toString();
JLabel renderer = new JLabel(label);
renderer.setForeground(Color.black);
renderer.setBackground(XConstants.textbackground);
renderer.setOpaque(true);
renderer.setFont(XConstants.textfont);
return renderer;
}
/**
* Interfaz ItemListener
*/
public void itemStateChanged(ItemEvent e) {
if(functionform.getSelectedItem() == null) return;
if(e.getStateChange() != ItemEvent.SELECTED) return;
String def = (String) functionform.getSelectedItem();
int dot = def.indexOf('.');
String pkgname = def.substring(0, dot);
String funcname = def.substring(dot+1);
if(famcopy == null ||
!pkgname.equals(famcopy.getPackageName()) ||
!funcname.equals(famcopy.getFunctionName()) ) {
XflPackageBank bank = editor.getXfedit().getXflPackageBank();
famcopy = (Family) bank.instantiate(pkgname, funcname, XflPackage.FAMILY);
famcopy.set(labelform.getText(),type);
setData();
}
functionform.setSelectedItem(null);
}
//----------------------------------------------------------------------------//
// M�TODOS PRIVADOS //
//----------------------------------------------------------------------------//
/**
* Construye la ventana
*/
private void build() {
String label[] = { "Set", "Refresh", "Cancel" };
String command[] = { "Set", "Refresh", "Cancel" };
XCommandForm form = new XCommandForm(label, command, this);
form.setCommandWidth(130);
labelform = new XTextForm("Label");
labelform.setLabelWidth(100);
labelform.setFieldWidth(200);
labelform.setAlignment(JLabel.CENTER);
functionform = new XComboBox("Function");
functionform.setWidth(100,200);
functionform.setRenderer(this);
functionform.addItemListener(this);
Box box1 = new Box(BoxLayout.Y_AXIS);
box1.add(labelform);
box1.add(functionform);
Box labelbox = new Box(BoxLayout.X_AXIS);
labelbox.add(Box.createHorizontalStrut(5));
labelbox.add(box1);
labelbox.add(Box.createHorizontalStrut(5));
paramform = new XTextForm[MINSIZE];
for(int i=0; i<paramform.length; i++) {
paramform[i] = new XTextForm("",this);
paramform[i].setEditable(false);
paramform[i].setLabelWidth(100);
paramform[i].setFieldWidth(200);
paramform[i].setFieldEnabled(false);
paramform[i].setAlignment(JLabel.CENTER);
paramform[i].setActionCommand(""+i);
}
parambox = new Box(BoxLayout.Y_AXIS);
for(int i=0; i<paramform.length; i++) parambox.add(paramform[i]);
Box pbox = new Box(BoxLayout.X_AXIS);
pbox.add(Box.createHorizontalStrut(5));
pbox.add(parambox);
pbox.add(Box.createHorizontalStrut(5));
Box leftbox = new Box(BoxLayout.Y_AXIS);
leftbox.add(Box.createVerticalStrut(5));
leftbox.add(labelbox);
leftbox.add(Box.createVerticalStrut(5));
leftbox.add(new XLabel("Parameters"));
leftbox.add(Box.createVerticalStrut(5));
leftbox.add(new JScrollPane(pbox));
leftbox.add(Box.createVerticalStrut(5));
leftbox.add(Box.createGlue());
this.graph = new XfeditFamilyGraphPanel(famcopy,300);
Box hbox = new Box(BoxLayout.X_AXIS);
hbox.add(Box.createHorizontalStrut(5));
hbox.add(leftbox);
hbox.add(Box.createHorizontalStrut(5));
hbox.add(this.graph);
hbox.add(Box.createHorizontalStrut(5));
Container content = getContentPane();
content.setLayout(new BoxLayout(content,BoxLayout.Y_AXIS));
content.add(new XLabel("Parameter Selection"));
content.add(Box.createVerticalStrut(5));
content.add(hbox);
content.add(Box.createVerticalStrut(5));
content.add(Box.createGlue());
content.add(form);
content.add(Box.createGlue());
setFont(XConstants.font);
setLocationRelativeTo(editor.getXfedit());
pack();
}
/**
* Actualiza la lista de funciones disponibles
*/
private void setList() {
XflPackageBank bank = this.editor.getXfedit().getXflPackageBank();
Vector available = bank.getFunctionNames(XflPackage.FAMILY);
functionform.setList(available);
}
/**
* Actualiza los datos de la familia
*/
private void setData() {
if(famcopy == null) return;
labelform.setText(famcopy.getLabel());
Parameter[] single = famcopy.getSingleParameters();
Parameter[] list = famcopy.getParamList();
String listname = famcopy.getParamListName();
if(famcopy.hasParamList()) index = single.length + list.length;
else index = single.length;
ensureSize();
for(int i=0; i<single.length; i++) {
paramform[i].setText(""+single[i].value);
paramform[i].setLabel(single[i].getName());
paramform[i].setEditable(true);
paramform[i].setFieldEnabled(true);
}
for(int i=single.length; i<index; i++) {
String paramname = listname+"["+(i-single.length)+"]";
paramform[i].setText(""+list[i-single.length].value);
paramform[i].setLabel(paramname);
paramform[i].setEditable(true);
paramform[i].setFieldEnabled(true);
}
for(int i=index; i<paramform.length; i++) {
paramform[i].setText("");
paramform[i].setLabel("");
paramform[i].setEditable(false);
paramform[i].setFieldEnabled(false);
}
if(famcopy.hasParamList()) paramform[index].setLabel("New");
graph.setFamily(famcopy);
graph.repaint();
}
/**
* Obtiene los datos de la ventana
*/
private boolean getData() {
if(famcopy == null) return false;
boolean numeric = true;
famcopy.setLabel(labelform.getText());
Parameter[] single = famcopy.getSingleParameters();
Parameter[] list = famcopy.getParamList();
for(int i=0; i<single.length; i++) {
try { single[i].value = Double.parseDouble(paramform[i].getText());}
catch (NumberFormatException ex) {
paramform[i].setText(""+single[i].value);
numeric = false;
}
}
if(famcopy.hasParamList()) for(int i=0; i<list.length; i++) {
String text = paramform[i+single.length].getText();
try { list[i].value = Double.parseDouble(text);}
catch (NumberFormatException ex) {
paramform[i+single.length].setText(""+list[i].value);
numeric = false;
}
}
if(!numeric) {
XDialog.showMessage(editor,"Not a numeric value");
return false;
}
if(!famcopy.test()) {
XDialog.showMessage(editor,"Invalid parameters");
return false;
}
boolean wrong = false;
int members = famcopy.members();
FamiliarMemFunc[] fmf = type.getFamiliarMembershipFunctions();
for(int i=0; i<fmf.length; i++) {
if(fmf[i].getFamily() == famorig && fmf[i].getIndex()>=members) wrong = true;
}
if(wrong) {
XDialog.showMessage(editor,"Insuficient members for defined MFs");
return false;
}
return true;
}
/**
* Redimensiona el panel de par�metros para asegurar que se
* puedan editar todos los par�metros de la familia
*/
private void ensureSize() {
while(index < paramform.length-1 && paramform.length > MINSIZE) {
parambox.remove(paramform[paramform.length-1]);
XTextForm at[] = new XTextForm[paramform.length-1];
System.arraycopy(paramform,0,at,0,paramform.length-1);
paramform = at;
}
for(int i=index-paramform.length; i>=0; i--) {
XTextForm nt = new XTextForm(" ",this);
nt.setLabelWidth(100);
nt.setFieldWidth(200);
nt.setAlignment(JButton.CENTER);
nt.setActionCommand(""+paramform.length);
parambox.add(nt);
XTextForm at[] = new XTextForm[paramform.length+1];
System.arraycopy(paramform,0,at,0,paramform.length);
at[paramform.length] = nt;
paramform = at;
}
}
/**
* A�ade un campo para un nuevo par�metro
*/
private void addParameter() {
if(!famcopy.hasParamList()) return;
String listname = famcopy.getParamListName();
Parameter[] list = famcopy.getParamList();
Parameter np = new Parameter(listname);
Parameter p[] = new Parameter[list.length+1];
System.arraycopy(list,0,p,0,list.length);
p[list.length] = np;
famcopy.setParamList(p);
index++;
ensureSize();
String paramname = listname+"["+(index-1)+"]";
paramform[index-1].setLabel(paramname);
paramform[index-1].setEditable(true);
paramform[index-1].setFieldEnabled(true);
paramform[index].setLabel("New");
paramform[index].setEditable(false);
paramform[index].setFieldEnabled(false);
}
/**
* Elimina un campo para introducir un par�metro
*/
private void removeParameter(int i) {
if(!famcopy.hasParamList()) return;
Parameter[] single = famcopy.getSingleParameters();
Parameter[] list = famcopy.getParamList();
if(i<single.length) return;
for(int j=i+1; j<index; j++) {
paramform[j-1].setText(paramform[j].getText());
list[j-single.length-1].value = list[j-single.length].value;
}
Parameter ap[] = new Parameter[list.length-1];
System.arraycopy(list,0,ap,0,list.length-1);
famcopy.setParamList(ap);
index--;
paramform[index].setLabel("New");
paramform[index].setText("");
paramform[index].setEditable(false);
paramform[index].setFieldEnabled(false);
paramform[index+1].setLabel("");
paramform[index+1].setText("");
ensureSize();
}
/**
* Actualiza la familia y cierra la ventana
*/
private void set() {
if(!getData()) return;
if(!XConstants.isIdentifier( famcopy.getLabel() )) {
labelform.setText("");
famcopy.setLabel("");
XDialog.showMessage(editor,"Invalid label");
return;
}
Family[] pmf = type.getFamilies();
for(int i=0; i<pmf.length; i++)
if(pmf[i] != famorig && pmf[i].equals(famcopy.getLabel())) {
String msg = "Family "+famcopy.getLabel()+" already exists";
labelform.setText("");
famcopy.setLabel("");
XDialog.showMessage(editor,msg);
return;
}
if(famorig == null) editor.addFamily(famcopy);
else editor.exchangeFamily(famorig,famcopy);
setVisible(false);
}
}