//--------------------------------------------------------------------------------//
// 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.xfsg;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.util.Collection;
import java.util.LinkedList;
import javax.swing.BorderFactory;
import javax.swing.JTextArea;
import xfuzzy.lang.ModuleCall;
import xfuzzy.lang.SystemModule;
import xfuzzy.lang.Variable;
import xfuzzy.util.XConstants;
/**
* Clase que se utiliza para representar gr�ficamente el sistema difuso definido
* en el lenguaje XFL3. Para realizar esta clase se han utilizado gran parte de
* las funciones del m�dulo Xfedit.
*
* @author Jes�s Izquierdo Tena
*/
public class XfsgStructure extends JTextArea {
/**
* C�digo asociado a la clase serializable
*/
private static final long serialVersionUID = 95505666603039L;
// ----------------------------------------------------------------------------//
// MIEMBROS PRIVADOS //
// ----------------------------------------------------------------------------//
/**
* Descripci�n de la estructura a mostrar
*/
private SystemModule system;
/**
* Componentes de llamadas a m�dulos que forman parte de la estructura
*/
private XfsgCallComponent call[];
/**
* Puntos (cuadraditos) que representan variables de entrada del sistema
*/
private XfsgVariableDot inputdot[];
/**
* Puntos (cuadraditos) que representan variables de salida del sistema
*/
private XfsgVariableDot outputdot[];
/**
* Puntos (cuadraditos) que representan variables de internas del sistema
*/
private XfsgVariableDot dot[];
/**
* Punto seleccionado
*/
private XfsgVariableDot selecteddot;
/**
* Fuente de letra para etiquetar las variables
*/
private FontMetrics fm;
/**
* Niveles de encadenamiento de m�dulos en la estructura
*/
private int levels;
/**
* Anchura de las diferentes zonas a representar: etiquetas de las variables
* de entrada, de salida, internas y anchura de los componentes de llamada
*/
private int inputwidth, outputwidth, callwidth, varwidth;
/**
* Altura total de la representaci�n
*/
private int totalheight;
/**
* Contador de canales para las l�neas de conexi�n
*/
public int counter;
// ----------------------------------------------------------------------------//
// M�TODOS P�BLICOS //
// ----------------------------------------------------------------------------//
/**
* Constructor para la aplicaci�n Xfedit
*/
public XfsgStructure(SystemModule system) {
super();
this.system = system;
build();
}
/**
* Calcula los componentes para representar la estructura
*/
public void setValues() {
Variable input[] = system.getInputs();
Variable output[] = system.getOutputs();
ModuleCall rcall[] = system.getModuleCalls();
this.fm = getFontMetrics(getFont());
this.counter = 0;
this.dot = new XfsgVariableDot[0];
this.inputdot = new XfsgVariableDot[input.length];
this.outputdot = new XfsgVariableDot[output.length];
this.call = new XfsgCallComponent[rcall.length];
for (int i = 0; i < input.length; i++) {
inputdot[i] = new XfsgVariableDot(this, input[i], 0, true);
addDot(inputdot[i]);
}
for (int i = 0; i < output.length; i++) {
outputdot[i] = new XfsgVariableDot(this, output[i], 0, false);
addDot(outputdot[i]);
}
for (int i = 0; i < rcall.length; i++) {
call[i] = new XfsgCallComponent(this, rcall[i]);
}
this.inputwidth = 0;
this.outputwidth = 0;
this.callwidth = 80;
this.levels = 0;
for (int i = 0; i < input.length; i++)
inputwidth = Math.max(inputwidth, fm.stringWidth(input[i]
.toString()));
for (int i = 0; i < output.length; i++)
outputwidth = Math.max(outputwidth, fm.stringWidth(output[i]
.toString()));
for (int i = 0; i < rcall.length; i++) {
int labelwidth = fm.stringWidth(rcall[i].getName()) + 10;
callwidth = Math.max(callwidth, labelwidth);
}
for (int i = 0; i < call.length; i++)
if (call[i].level > levels)
levels = call[i].level;
this.inputwidth += 20;
this.outputwidth += 20;
this.levels++;
for (int i = 0; i < outputdot.length; i++)
outputdot[i].level = levels;
this.varwidth = 30 + 3 * counter;
Dimension size = getSize();
int width = (size.width > 350 ? size.width : 350);
int vwidth = (width - inputwidth - outputwidth - levels * callwidth)
/ (levels + 1);
if (varwidth < vwidth)
varwidth = vwidth;
int twidth = inputwidth + levels * callwidth + (levels + 1) * varwidth
+ outputwidth;
if (twidth < width)
twidth = width;
int theight = 70 + 3 * counter;
for (int lv = 0; lv < levels; lv++) {
int lvheight = 70 + 3 * counter;
for (int i = 0; i < call.length; i++)
if (call[i].level == lv)
lvheight += call[i].height + 20;
if (lvheight > theight)
theight = lvheight;
}
setPreferredSize(new Dimension(twidth, theight));
}
/**
* A�adir un punto (variable) a la gr�fica
*/
public void addDot(XfsgVariableDot ndot) {
XfsgVariableDot adot[] = new XfsgVariableDot[this.dot.length + 1];
System.arraycopy(this.dot, 0, adot, 0, this.dot.length);
adot[this.dot.length] = ndot;
this.dot = adot;
}
/**
* Busca el punto correspondiente a una variable
*/
public XfsgVariableDot searchOriginDot(Variable var) {
if (var == null)
return null;
if (var.isInner() || var.isOutput())
for (int i = 0; i < dot.length; i++) {
if (dot[i].sysvar == var && dot[i].isInternal()
&& dot[i].isOutput())
return dot[i];
}
else
for (int i = 0; i < dot.length; i++) {
if (dot[i].sysvar == var && dot[i].isGlobal())
return dot[i];
}
return null;
}
/**
* Genera el contenido del panel
*/
private void build() {
setBackground(XConstants.textbackground);
setBorder(BorderFactory.createLoweredBevelBorder());
setFont(XConstants.textfont);
setEditable(false);
setValues();
}
/**
* Sobreescribe el m�todo que pinta el panel
*/
public void paint(Graphics g) {
super.paint(g);
paintBase(g);
}
/**
* Pinta la estructura
*/
private void paintBase(Graphics g) {
Dimension size = getSize();
this.totalheight = size.height;
Variable input[] = system.getInputs();
Variable output[] = system.getOutputs();
int ih = (size.height - 35 - 3 * counter) / (input.length + 1);
int oh = (size.height - 35 - 3 * counter) / (output.length + 1);
int sw = size.width - inputwidth - outputwidth;
g.setColor(XConstants.systembg);
g.fillRoundRect(inputwidth, 10, sw, size.height - 20, 15, 15);
g.setColor(Color.black);
g.drawRoundRect(inputwidth, 10, sw, size.height - 20, 15, 15);
for (int i = 0; i < inputdot.length; i++) {
inputdot[i].setPoint(inputwidth, 10 + ih + ih * i);
inputdot[i].paintDot(g);
}
for (int i = 0; i < outputdot.length; i++) {
outputdot[i].setPoint(size.width - outputwidth, 10 + oh + oh * i);
outputdot[i].paintDot(g);
}
varwidth = (size.width - inputwidth - outputwidth - levels * callwidth)
/ (levels + 1);
for (int lv = 0; lv < levels; lv++) {
int lvcounter = 0, lvheight = 0;
for (int i = 0; i < call.length; i++)
if (call[i].level == lv) {
lvcounter++;
lvheight += call[i].height;
}
int ch = (size.height - 35 - lvheight - 3 * counter)
/ (lvcounter + 1);
int cpos = inputwidth + varwidth + lv * (varwidth + callwidth);
int ypos = 10 + ch;
for (int i = 0; i < call.length; i++)
if (call[i].level == lv) {
call[i].paintCall(g, cpos, ypos, callwidth);
ypos += ch + call[i].height;
}
}
for (int i = 0; i < call.length; i++)
call[i].paintLinks(g);
}
/**
* Pinta un enlace
*/
public void paintLink(Graphics g, XfsgVariableDot orig, XfsgVariableDot dest) {
if (orig == null || dest == null)
return;
if (orig.isNull())
return;
if (dest.isNull())
return;
String aux1 = "null", aux2 = "null";
Color channelcolor = Color.black;
switch (orig.channel % 4) {
case 0:
channelcolor = Color.black;
break;
case 1:
channelcolor = Color.red;
break;
case 2:
channelcolor = Color.blue;
break;
case 3:
channelcolor = Color.green;
break;
}
g.setColor(channelcolor);
// System.out.println("origen: "+orig.sysvar.getName());
// System.out.println("destino: "+dest.sysvar.getName());
Collection<int[]> c = new LinkedList<int[]>();
int[] puntos;
if (orig.level == dest.level) {
int channel = orig.x + varwidth / 2 + (orig.channel - counter / 2)
* 3;
g.drawLine(orig.x, orig.y, channel, orig.y);
puntos = new int[4];
puntos[0] = orig.x;
puntos[1] = orig.y;
puntos[2] = channel;
puntos[3] = orig.y;
c.add(puntos);
g.drawLine(channel, orig.y, channel, dest.y);
puntos = new int[4];
puntos[0] = channel;
puntos[1] = orig.y;
puntos[2] = channel;
puntos[3] = dest.y;
c.add(puntos);
g.drawLine(channel, dest.y, dest.x, dest.y);
puntos = new int[4];
puntos[0] = channel;
puntos[1] = dest.y;
puntos[2] = dest.x;
puntos[3] = dest.y;
c.add(puntos);
if (orig.call != null)
aux1 = orig.call.call.getName();
if (dest.call != null)
aux2 = dest.call.call.getName();
// if(orig.call!=null && dest.call!=null)
// System.out.println(orig.sysvar.getName()+orig.call.call.getName()+dest.call.call.getName());
new XfsgArchitecturesSimulink(orig.sysvar.getName() + aux1 + aux2,
c);
// System.out.println(orig.sysvar.getName()+aux1+aux2);
if (selecteddot != dest && selecteddot != orig)
return;
g.drawLine(orig.x, orig.y - 1, channel + 1, orig.y - 1);
g.drawLine(channel + 1, orig.y - 1, channel + 1, dest.y - 1);
g.drawLine(channel + 1, dest.y - 1, dest.x, dest.y - 1);
} else {
int channel1 = orig.x + varwidth / 2 + (orig.channel - counter / 2)
* 3;
int channel2 = totalheight - 25 - 3 * orig.channel;
int channel3 = dest.x - varwidth / 2 + (orig.channel - counter / 2)
* 3;
g.drawLine(orig.x, orig.y, channel1, orig.y);
puntos = new int[4];
puntos[0] = orig.x;
puntos[1] = orig.y;
puntos[2] = channel1;
puntos[3] = orig.y;
c.add(puntos);
g.drawLine(channel1, orig.y, channel1, channel2);
puntos = new int[4];
puntos[0] = channel1;
puntos[1] = orig.y;
puntos[2] = channel1;
puntos[3] = channel2;
c.add(puntos);
g.drawLine(channel1, channel2, channel3, channel2);
puntos = new int[4];
puntos[0] = channel1;
puntos[1] = channel2;
puntos[2] = channel3;
puntos[3] = channel2;
c.add(puntos);
g.drawLine(channel3, channel2, channel3, dest.y);
puntos = new int[4];
puntos[0] = channel3;
puntos[1] = channel2;
puntos[2] = channel3;
puntos[3] = dest.y;
c.add(puntos);
g.drawLine(channel3, dest.y, dest.x, dest.y);
puntos = new int[4];
puntos[0] = channel3;
puntos[1] = dest.y;
puntos[2] = dest.x;
puntos[3] = dest.y;
c.add(puntos);
// if(orig.call!=null && dest.call!=null)
// System.out.println(orig.sysvar.getName()+orig.call.call.getName()+dest.call.call.getName());
if (orig.call != null)
aux1 = orig.call.call.getName();
if (dest.call != null)
aux2 = dest.call.call.getName();
new XfsgArchitecturesSimulink(orig.sysvar.getName() + aux1 + aux2,
c);
// System.out.println(orig.sysvar.getName()+aux1+aux2);
if (selecteddot != dest && selecteddot != orig)
return;
channel1++;
channel2--;
channel3++;
g.drawLine(orig.x, orig.y - 1, channel1, orig.y - 1);
g.drawLine(channel1, orig.y - 1, channel1, channel2);
g.drawLine(channel1, channel2, channel3, channel2);
g.drawLine(channel3, channel2, channel3, dest.y);
g.drawLine(channel3, dest.y - 1, dest.x, dest.y - 1);
}
g.setColor(Color.black);
}
/**
* Busca el punto correspondiente a una variable
*/
public XfsgVariableDot searchDot(Variable var) {
if (var == null)
return null;
if (var.isInner())
for (int i = 0; i < dot.length; i++) {
if (dot[i].sysvar == var && dot[i].isOrigin())
return dot[i];
}
else
for (int i = 0; i < dot.length; i++) {
if (dot[i].sysvar == var && dot[i].isGlobal())
return dot[i];
}
return null;
}
}