//--------------------------------------------------------------------------------// // 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 javax.swing.event.*; import java.awt.*; import java.awt.event.*; import java.util.Vector; /** * Ventana de edici�n de una base de reglas * * @author Francisco Jos� Moreno Velo * */ public class XfeditRulebaseEditor extends JDialog implements ActionListener, ChangeListener, ListSelectionListener, ItemListener, KeyListener, MouseListener, WindowListener { /** * C�digo asociado a la clase serializable */ private static final long serialVersionUID = 95505666603028L; //----------------------------------------------------------------------------// // MIEMBROS PRIVADOS // //----------------------------------------------------------------------------// /** * Referencia al editor que realiza la llamada a XfeditRulebaseEditor */ private Xfedit xfeditor; /** * Sistema difuso en edici�n */ private Specification spec; /** * Objeto original que describe la base de reglas a editar */ private Rulebase original; /** * Copia de trabajo sobre la que se realizan los cambios * de edici�n de la base de reglas */ private Rulebase copy; /** * Campo para introducir el nombre de la base de reglas */ private XTextForm nameform; /** * Campo para seleccionar el conjunto de operadores a utilizar * en la base de reglas */ private XComboBox opsetbox; /** * Lista de variables de entrada de la base de reglas */ private XList inputlist; /** * Lista de variables de salida de la base de reglas */ private XList outputlist; /** * Men� desplegable asociado a la lista de variables de entrada */ private JPopupMenu inputpopup; /** * Men� desplegable asociado a la lista de variables de entrada */ private JPopupMenu outputpopup; /** * Panel con pesta�as para las diferentes formas de edici�n de * la base de reglas */ private JTabbedPane tabbed; /** * Panel de edici�n seleccionado */ private JPanel selectedtab; /** * Panel de edici�n en formato libre */ private XfeditRulebaseFreePanel freepanel; /** * Panel de edici�n en formato tabular */ private XfeditRulebaseTablePanel tablepanel; /** * Panel de edici�n en formato matricial */ private XfeditRulebaseMatrixPanel matrixpanel; //----------------------------------------------------------------------------// // CONSTRUCTOR // //----------------------------------------------------------------------------// /** * Constructor */ public XfeditRulebaseEditor(Xfedit xfeditor, Rulebase rulebase) { super(xfeditor,"Xfedit",false); this.xfeditor = xfeditor; this.spec = xfeditor.getSpecification(); this.original = rulebase; if(this.original != null) { this.original.setEditing(true); this.copy = (Rulebase) this.original.clone(); } else this.copy = new Rulebase(""); build(); refreshAll(); } //----------------------------------------------------------------------------// // M�TODOS P�BLICOS // //----------------------------------------------------------------------------// /** * Genera una ventana de edicion de una base de reglas */ public static void showRulebaseEditor(Xfedit xfeditor, Rulebase rb){ XfeditRulebaseEditor editor = new XfeditRulebaseEditor(xfeditor,rb); editor.setVisible(true); editor.repaint(); } /** * Obtiene una referencia a la base de reglas editada */ public Rulebase getWorkingCopy() { return this.copy; } /** * Obtiene la referencia al sistema difuso editado */ public Specification getSpecification() { return this.spec; } /** * Interfaz ActionListener */ public void actionPerformed(ActionEvent e) { String command = e.getActionCommand(); if(command.equals("Ok")) ok(); else if(command.equals("Apply")) apply(); else if(command.equals("Reload")) reload(); else if(command.equals("Cancel")) cancel(); else if(command.equals("NewInput")) newVariable(Variable.INPUT); else if(command.equals("EditInput")) editVariable(Variable.INPUT); else if(command.equals("RemoveInput")) removeVariable(Variable.INPUT); else if(command.equals("NewOutput")) newVariable(Variable.OUTPUT); else if(command.equals("EditOutput")) editVariable(Variable.OUTPUT); else if(command.equals("RemoveOutput")) removeVariable(Variable.OUTPUT); } /** * Interfaz ChangeListener */ public void stateChanged(ChangeEvent e) { JPanel selected = (JPanel) tabbed.getSelectedComponent(); if(selected == selectedtab) return; if(!getRules()) { tabbed.setSelectedComponent(selectedtab); return; } if(selected == freepanel) freepanel.refresh(copy); if(selected == tablepanel) tablepanel.refresh(copy); if(selected == matrixpanel) matrixpanel.refresh(copy); selectedtab = selected; } /** * Interfaz ListSelectionListener */ public void valueChanged(ListSelectionEvent e) { if(e.getSource() == inputlist.getList() ) { if(inputlist.isSelectionEmpty()) return; outputlist.clearSelection(); } else { if(outputlist.isSelectionEmpty()) return; inputlist.clearSelection(); } if(selectedtab == tablepanel) tablepanel.clearSelection(); if(selectedtab == freepanel) freepanel.clearSelection(); } /** * Interfaz ItemListener */ public void itemStateChanged(ItemEvent e) { if(e.getStateChange() != ItemEvent.SELECTED) return; try { Operatorset selection = (Operatorset) opsetbox.getSelectedItem(); if(selection == null) return; copy.setOperatorset(selection); } catch(Exception ex) { copy.setOperatorset(new Operatorset()); } } /** * Interfaz KeyListener. Acci�n al soltar una tecla */ public void keyReleased(KeyEvent e) { int kind = -1; if(e.getSource() == inputlist.getList() ) kind = Variable.INPUT; if(e.getSource() == outputlist.getList() ) kind = Variable.OUTPUT; if(e.getKeyCode() == KeyEvent.VK_DELETE) { e.consume(); removeVariable(kind); } if(e.getKeyCode() == KeyEvent.VK_BACK_SPACE) { e.consume(); removeVariable(kind); } if(e.getKeyCode() == KeyEvent.VK_INSERT) { e.consume(); newVariable(kind); } if(e.getKeyCode() == KeyEvent.VK_ENTER) { e.consume(); editVariable(kind); } if(e.getKeyCode() == 226) { e.consume(); editVariable(kind); } } /** * Interfaz KeyListener. Acci�n al apretar una tecla */ public void keyPressed(KeyEvent e) { } /** * Interfaz KeyListener. Acci�n al teclear. */ public void keyTyped(KeyEvent e) { } /** * Interfaz MouseListener. Acci�n al pulsar el rat�n */ public void mouseClicked(MouseEvent e) { if(e.getClickCount() != 2) return; int kind = -1; if(e.getSource() == inputlist.getList() ) kind = Variable.INPUT; if(e.getSource() == outputlist.getList() ) kind = Variable.OUTPUT; editVariable(kind); } /** * Interfaz MouseListener. Acci�n al apretar un bot�n del rat�n */ public void mousePressed(MouseEvent e) { if(!e.isPopupTrigger()) return; if(e.getSource() == inputlist.getList()) { inputpopup.show((Component) e.getSource(), e.getX(), e.getY()); } if(e.getSource() == outputlist.getList() ) { outputpopup.show((Component) e.getSource(), e.getX(), e.getY()); } } /** * Interfaz MouseListener. Acci�n al soltar un bot�n del rat�n */ public void mouseReleased(MouseEvent e) { if(!e.isPopupTrigger()) return; if(e.getSource() == inputlist.getList()) { inputpopup.show((Component) e.getSource(), e.getX(), e.getY()); } if(e.getSource() == outputlist.getList() ) { outputpopup.show((Component) e.getSource(), e.getX(), e.getY()); } } /** * Interfaz MouseListener. Acci�n al entrar en la ventana */ public void mouseEntered(MouseEvent e) { } /** * Interfaz MouseListener. Acci�n al salir de la ventana */ public void mouseExited(MouseEvent e) { } /** * Interfaz WindowListener. Acci�n al abrir la ventana */ public void windowOpened(WindowEvent e) { } /** * Interfaz WindowListener. Acci�n al cerrar la ventana */ public void windowClosing(WindowEvent e) { cancel(); } /** * Interfaz WindowListener. Acci�n al finalizar el cierre */ public void windowClosed(WindowEvent e) { } /** * Interfaz WindowListener. Acci�n al minimizar la ventana */ public void windowIconified(WindowEvent e) { } /** * Interfaz WindowListener. Acci�n al maximizar la ventana */ public void windowDeiconified(WindowEvent e) { } /** * Interfaz WindowListener. Acci�n al activar la ventana */ public void windowActivated(WindowEvent e) { } /** * Interfaz WindowListener. Acci�n al desactivar la ventana */ public void windowDeactivated(WindowEvent e) { } //----------------------------------------------------------------------------// // M�TODOS PRIVADOS // //----------------------------------------------------------------------------// /** * Genera el contenido de la ventana */ private void build() { String lb[] = {"Ok","Apply","Reload","Cancel"}; XCommandForm form = new XCommandForm(lb,this); form.setCommandWidth(120); form.block(); nameform = new XTextForm("Name"); nameform.setWidth(130,130); nameform.setAlignment(JLabel.CENTER); opsetbox = new XComboBox("Operatorset"); opsetbox.setWidth(130,130); opsetbox.addItemListener(this); inputlist = new XList("Input variables"); inputlist.addListSelectionListener(this); inputlist.addKeyListener(this); inputlist.addMouseListener(this); outputlist = new XList("Output variables"); outputlist.addListSelectionListener(this); outputlist.addKeyListener(this); outputlist.addMouseListener(this); JPanel leftbox = new JPanel(); leftbox.setLayout(new BoxLayout(leftbox,BoxLayout.Y_AXIS)); leftbox.add(nameform); leftbox.add(Box.createVerticalStrut(5)); leftbox.add(opsetbox); leftbox.add(Box.createVerticalStrut(5)); leftbox.add(inputlist); leftbox.add(Box.createVerticalStrut(5)); leftbox.add(outputlist); Dimension pref = leftbox.getPreferredSize(); Dimension maxd = leftbox.getMaximumSize(); leftbox.setMaximumSize(new Dimension(pref.width, maxd.height)); Box rightbox = new Box(BoxLayout.Y_AXIS); tabbed = new JTabbedPane(); freepanel = new XfeditRulebaseFreePanel(); tablepanel = new XfeditRulebaseTablePanel(); matrixpanel = new XfeditRulebaseMatrixPanel(); tabbed.addTab("Free form",freepanel); tabbed.addTab("Table form",tablepanel); tabbed.addTab("Matrix form",matrixpanel); tabbed.addChangeListener(this); selectedtab = freepanel; rightbox.add(tabbed); Box hbox = new Box(BoxLayout.X_AXIS); hbox.add(Box.createHorizontalStrut(5)); hbox.add(leftbox); hbox.add(Box.createHorizontalStrut(5)); hbox.add(rightbox); hbox.add(Box.createHorizontalStrut(5)); Container content = getContentPane(); content.setLayout(new BoxLayout(content,BoxLayout.Y_AXIS)); content.add(new XLabel("Rulebase Edition")); content.add(Box.createVerticalStrut(5)); content.add(hbox); content.add(form); setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); addWindowListener(this); setFont(XConstants.font); setSize(new Dimension(910,500)); setLocationRelativeTo(xfeditor); createPopups(); } /** * Crea los men�s desplegables */ private void createPopups() { String ilabel[]= { "New Input Variable","Edit Input Variable", "Remove Input Variable" }; String icommand[] = { "NewInput", "EditInput", "RemoveInput" }; inputpopup = new JPopupMenu(); JMenuItem inputitem[] = new JMenuItem[icommand.length]; for(int i=0; i<icommand.length; i++) { inputitem[i] = new JMenuItem(ilabel[i]); inputitem[i].setActionCommand(icommand[i]); inputitem[i].addActionListener(this); inputitem[i].setFont(XConstants.font); inputpopup.add(inputitem[i]); } String olabel[]= { "New Output Variable","Edit Output Variable", "Remove Output Variable" }; String ocommand[] = { "NewOutput", "EditOutput", "RemoveOutput" }; outputpopup = new JPopupMenu(); JMenuItem outputitem[] = new JMenuItem[ocommand.length]; for(int i=0; i<ocommand.length; i++) { outputitem[i] = new JMenuItem(olabel[i]); outputitem[i].setActionCommand(ocommand[i]); outputitem[i].addActionListener(this); outputitem[i].setFont(XConstants.font); outputpopup.add(outputitem[i]); } } /** * Lee el contenido del panel de edici�n de reglas */ private boolean getRules() { boolean rulesok = false; if(selectedtab == freepanel) rulesok = freepanel.getRules(copy); if(selectedtab == tablepanel) rulesok = tablepanel.getRules(copy); if(selectedtab == matrixpanel) rulesok = matrixpanel.getRules(copy); if(!rulesok) Toolkit.getDefaultToolkit().beep(); return rulesok; } /** * Actualiza el contenido de las diferentes �reas del editor */ private void refresh() { inputlist.setListData(copy.getInputs()); outputlist.setListData(copy.getOutputs()); if(selectedtab == freepanel) freepanel.refresh(copy); if(selectedtab == tablepanel) tablepanel.refresh(copy); if(selectedtab == matrixpanel) matrixpanel.refresh(copy); repaint(); } /** * Actualiza el contenido, incluyendo la lista de operadores */ private void refreshAll() { nameform.setText(copy.getName()); Vector opsetlist = new Vector(); opsetlist.add("default"); Operatorset[] opsetdef = spec.getOperatorsets(); for(int i=0; i<opsetdef.length; i++) opsetlist.add(opsetdef[i]); opsetbox.setList(opsetlist); Operatorset used = copy.getOperatorset(); if(used == null || used.isDefault()) opsetbox.setSelectedIndex(0); else opsetbox.setSelectedItem(used); refresh(); } /** * Lee y verifica el nombre de la base de reglas */ private boolean getRulebaseName() { String name = nameform.getText(); if(!XConstants.isIdentifier(name)) { nameform.setText(""); XDialog.showMessage(nameform,"Invalid Name"); return false; } Rulebase search = spec.searchRulebase(name); if(search != null && search != original) { nameform.setText(""); XDialog.showMessage(nameform,"Invalid Name: Rulebase already exists"); return false; } copy.setName(name); return true; } //----------------------------------------------------------------------------// // M�todos de edici�n de las variables // //----------------------------------------------------------------------------// /** * Crea una nueva variable */ private void newVariable(int kind) { if(!getRules()) return; XfeditVariableDialog editor = new XfeditVariableDialog(kind,this); editor.setVisible(true); editor.repaint(); refresh(); } /** * Edita una variable existente */ private void editVariable(int kind) { if(!getRules()) return; Variable var; if(kind == Variable.INPUT) var = (Variable) inputlist.getSelectedValue(); else var = (Variable) outputlist.getSelectedValue(); if(var == null) return; XfeditVariableDialog editor = new XfeditVariableDialog(var,this); editor.setVisible(true); editor.repaint(); refresh(); } /** * Elimina una variable existente */ private void removeVariable(int kind) { if(!getRules()) return; Variable var; if(kind == Variable.INPUT) var = (Variable) inputlist.getSelectedValue(); else var = (Variable) outputlist.getSelectedValue(); if(var == null) return; if(var.isLinked()) { String msg[] = new String[2]; msg[0] = "Cannot remove variable \""+var.getName()+"\"."; msg[1] = "There are rules using this variable."; XDialog.showMessage(this,msg); return; } if(kind == Variable.INPUT) copy.removeInputVar(var); else copy.removeOutputVar(var); refresh(); } //----------------------------------------------------------------------------// // M�todos que desarrollan las acciones // //----------------------------------------------------------------------------// /** * Aplica las modificaci�nes introducidas en la edici�n */ private boolean tryApply() { if(!getRulebaseName()) return false; if(!getRules()) return false; if(original == null) spec.addRulebase(copy); else spec.exchangeRulebase(original,copy); original = copy; copy = (Rulebase) original.clone(); spec.setModified(true); return true; } /** * Aplica los cambios y cierra la ventana */ private void ok() { if( !tryApply() ) return; if(original != null) original.setEditing(false); copy.dispose(); xfeditor.refresh(); setVisible(false); } /** * Aplica los cambios y mantien abierta la ventana */ private void apply() { if(tryApply()) { refresh(); xfeditor.refresh(); } } /** * Desecha los cambios no almacenados */ private void reload() { copy.dispose(); if(original != null) copy = (Rulebase) original.clone(); else copy = new Rulebase(""); refreshAll(); } /** * Cierra la ventana sin almacenar los cambios */ private void cancel() { copy.dispose(); if(original != null) original.setEditing(false); xfeditor.refresh(); setVisible(false); } }