/*******************************************************************************
* See the NOTICE file distributed with this work for additional information
* regarding copyright ownership.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package hr.fer.zemris.vhdllab.applets.editor.automat;
//TODO prijelaz i equals i kad se koristi lista i dialog i kad se stvara novi prijelaz koji ide iz-u...
/*TODO strijelice srediti da ne bijeze..., elseprijelaz izlaz
* else prijelaz ispis kad ide iz jednog u drugo stanje,
* interni kod!! OK
* VHDL OK
* farbica ak niuje sve kak stima!!! OK
* resize!!! !!!!!!!!!!! samo jos dati minimume!!!
*/
import hr.fer.zemris.vhdllab.applets.editor.automaton.AUTParser;
import hr.fer.zemris.vhdllab.applets.editor.automaton.AUTPodatci;
import hr.fer.zemris.vhdllab.applets.editor.automaton.LanguageConstants;
import hr.fer.zemris.vhdllab.applets.editor.automaton.Prijelaz;
import hr.fer.zemris.vhdllab.applets.editor.automaton.Stanje;
import hr.fer.zemris.vhdllab.platform.manager.editor.Editor;
import hr.fer.zemris.vhdllab.validation.NameFormatConstraintValidator;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Point2D;
import java.awt.geom.QuadCurve2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.ResourceBundle;
import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.WindowConstants;
import org.xml.sax.SAXException;
/**
*
* @author ddelac
*
*/
public class AutoDrawer extends JPanel{
/**
* serialVersionUID
*/
private static final long serialVersionUID = 2847384905838330703L;
/**
* buffer u kojem se crta slika sklopa
*/
protected BufferedImage img = null;
/**
* zastavica koja govori dali je pritisnut neki element
*/
protected boolean pressed=false;
/**
* kolekcija koja sadrzi sva stanja automata
*/
protected LinkedList<Stanje> stanja=null;
/**
* kolekcija koja sadrzi sve prijelaze automata
*/
protected HashSet<Prijelaz> prijelazi=null;
/**
* varijabla sa osnovnovnim podatcima o samom automatu
*/
protected AUTPodatci podatci=null;
/**
* legenda u kutu
*/
private String legenda=null;
/**
* selektirano stanje...
*/
protected Stanje selektiran=null;
/**
* stanje koje se dodaje
*/
protected Stanje stanjeZaDodati=null;
/**
* prijelaz koji se dodaje
*/
protected Prijelaz prijelazZaDodati=null;
/**
* radijus krugova za stanja DEFAULT=20
*/
protected int radijus=20;
/**
* Stanja rada definirat ce dali se dodaje signal, dodaje prijelaz ili editira slika.
* stanjeRada=1 mjenjanje postojecih objekata
* stanjeRada=2 dodavanje novog stanja
* stanjeRada=3 dodavanje novog prijelaza (selekcija stanja iz)
* stanjeRada=4 dodavanje novog prijelaza (selekcija stanja u)
* stanjeRada=5 brisanje postojecih objekata
* stanjeRada=6 zadavanje pocetnog stanja
*/
protected int stanjeRada=1;
private boolean isOK=false;
/**
* Minimalne dimenzije do kojih se smije smanjivat editor.
*/
protected HashSet<String> listaSignala=null;
protected ResourceBundle bundle=null;
protected Editor editor;
/**
* konstruktor klase AutoDrawer, ne prima nikakve podatke, poziva createGUI() metodu
*
*/
public AutoDrawer(Editor editor) {
// super();
this.setOpaque(true);
createGUI();
//this.setPreferredSize(new Dimension(img.getWidth(),img.getHeight()));
this.editor = editor;
}
/*public AutoDrawer(String strpodatci){
super();
this.setOpaque(true);
setData(strpodatci);
if(podatci.ime!=null){
createGUI();
this.setPreferredSize(new Dimension(img.getWidth(),img.getHeight()));
isModified=false;
}
}*/
/**
* ova metoda iscrtava za pocetak kako ce izgledati sklop
*
*/
private void createGUI() {
img=new BufferedImage(this.getPreferredSize().width,this.getPreferredSize().height,BufferedImage.TYPE_3BYTE_BGR);
this.addMouseListener(new Mouse());
this.addMouseMotionListener(new Mouse2());
this.repaint();
}
/**
* metoda paintComponent klase JPanel overrideana
*/
@Override
protected void paintComponent(Graphics g) {
if(img == null) {
img=new BufferedImage(this.getWidth(),this.getHeight(),BufferedImage.TYPE_3BYTE_BGR);
} else {
if (img.getHeight()!=this.getHeight()||img.getWidth()!=this.getWidth()){
img=new BufferedImage(this.getWidth(),this.getHeight(),BufferedImage.TYPE_3BYTE_BGR);
}
if (stanjeRada!=4) nacrtajSklop();
g.drawImage(img,0,0,img.getWidth(),img.getHeight(),null);
}
}
/**
* Metoda get data propisana suceljem IEditor. Vraca podatke o sklopu.
*/
public String getData() {
return new CodeGenerator().generateInternalCode(podatci,prijelazi,stanja);
}
/**
* Metoda setData propisan suceljem IEditor. Dobiva podatke sklopa i na osnovi njih inicijalizira kolekcije
* stanja, prijelazi i podatci.
*/
public void setData(String data) {
AUTParser aut=new AUTParser();
try {
aut.AUTParse(data);
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
stanja=aut.stanja;
prijelazi=aut.prijelazi;
podatci=aut.podatci;
if(podatci.ime!=null)
parseLegend();
}
private void parseLegend() {
String ulazi="|";
String izlazi="|";
listaSignala=new HashSet<String>();
listaSignala.add("clock");
listaSignala.add("reset");
String[] redovi=podatci.interfac.split("\n");
for(int i=0;i<redovi.length;i++){
String[] rijeci=redovi[i].split(" ");
listaSignala.add(rijeci[0].toLowerCase());
if(rijeci[1].toUpperCase().equals("IN")) ulazi=new StringBuffer().append(ulazi).append(rijeci[0]).append("|").toString();
else izlazi=new StringBuffer().append(izlazi).append(rijeci[0]).append("|").toString();
}
legenda=new StringBuffer().append(bundle.getString(LanguageConstants.LEGEND_TITLE)).append(":\n")
.append(bundle.getString(LanguageConstants.LEGEND_IN)).append(":")
.append(ulazi).append("\n").append(bundle.getString(LanguageConstants.LEGEND_OUT))
.append(":").append(izlazi).toString();
}
/**
* Ova metoda zasluzna je crtanje automata uz stanjeRada==4.
*@param eventx ako je stanjeRada==4 daje x kordinatu misa
*@param eventy ako je stanjeRada==4 daje y koordinatu misa
*/
protected void nacrtajSklop(int eventx,int eventy){
if(dataSet()){
checkOKness();
// resizeComponent();
Graphics2D g=(Graphics2D)img.getGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(getOKColor());
g.fillRect(0,0,img.getWidth(),img.getHeight());
g.setColor(Color.WHITE);
g.fillRect(3,3,img.getWidth()-6,img.getHeight()-6);
//crtanje stanja
if(stanjeZaDodati!=null){
g.setColor(stanjeZaDodati.boja);
g.fillArc(stanjeZaDodati.ox,stanjeZaDodati.oy,2*radijus,2*radijus,0,360);
g.setColor(Color.WHITE);
g.fillArc(stanjeZaDodati.ox+radijus/5,stanjeZaDodati.oy+radijus/5,2*(radijus-radijus/5),2*(radijus-radijus/5),0,360);
}
for(Stanje st:stanja){
g.setColor(st.boja);
g.fillArc(st.ox,st.oy,2*radijus,2*radijus,0,360);
g.setColor(Color.WHITE);
g.fillArc(st.ox+radijus/5,st.oy+radijus/5,2*(radijus-radijus/5),2*(radijus-radijus/5),0,360);
g.setColor(st.boja);
if(st.ime.equals(podatci.pocetnoStanje)){
g.drawLine(st.ox-17,st.oy+radijus,st.ox,st.oy+radijus);
int[] xP=new int[3];
int[] yP=new int[3];
setXYP(xP,yP,st);
g.fillPolygon(xP,yP,3);
}
//upis u stanja
String tekst=null;
if(podatci.tip.equals("Moore"))
tekst=new StringBuffer().append(st.ime).append("/").append(st.izlaz).toString();
else if (podatci.tip.equals("Mealy"))
tekst=new StringBuffer().append(st.ime).toString();
g.setFont(new Font("Helvetica", Font.BOLD, radijus/2));
FontMetrics fm= g.getFontMetrics();
int xString=st.ox+radijus-fm.stringWidth(tekst)/2;
int yString=st.oy+radijus+fm.getAscent()/2;
g.drawString(tekst,xString,yString);
g.setColor(Color.WHITE);
}
//crtanje prijelaza
for(Prijelaz pr:prijelazi){
Stanje iz=null;
Stanje ka=null;
for(Stanje stanje:stanja){
if(stanje.ime.equals(pr.iz)) iz=stanje;
if(stanje.ime.equals(pr.u)) ka=stanje;
}
nacrtajPrijelaz(iz, ka,pr);
}
//crtanje else prijelaza
for(Stanje st1:stanja)
for(Stanje st2:stanja)
if(st1.els.equalsIgnoreCase(st2.ime))nacrtajPrijelaz(st1,st2,null);
if(stanjeRada==4){
for(Stanje st:stanja) if(st.ime==prijelazZaDodati.iz){
g.setColor(Color.CYAN);
g.drawLine(st.ox+radijus,st.oy+radijus,eventx,eventy);
break;
}
}
g.setColor(Color.BLACK);
String[] legendic=legenda.split("\n");
g.setFont(new Font("Arial", Font.BOLD, 10));
FontMetrics fm= g.getFontMetrics();
int odmak=legendic[0].length()>legendic[1].length()?
(legendic[0].length()>legendic[2].length()?fm.stringWidth(legendic[0]):fm.stringWidth(legendic[2])):
(legendic[1].length()>legendic[2].length()?fm.stringWidth(legendic[1]):fm.stringWidth(legendic[2]));
int xStr=img.getWidth()-odmak-10;
int yStr=fm.getHeight()+5;
g.drawString(legendic[0],xStr,yStr);
g.setFont(new Font("Arial", Font.PLAIN, 10));
fm= g.getFontMetrics();
yStr+=fm.getHeight();
g.drawString(legendic[1],xStr,yStr);
yStr+=fm.getHeight();
g.drawString(legendic[2],xStr,yStr);
repaint();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
}
}
protected void resizeComponent() {
int maxX=0;
int maxY=0;
for(Stanje st:stanja){
if(st.ox+2*radijus+10>maxX)maxX=st.ox+2*radijus+10;
if(st.oy+2*radijus+10>maxY)maxY=st.oy+2*radijus+10;
}
this.setPreferredSize(new Dimension(maxX,maxY));
// if(d.getHeight()< maxY || d.getWidth()< maxX){
// if(d.getHeight()> maxY) maxY = (int) d.getHeight();
// if(d.getWidth()>maxX) maxX = (int) d.getWidth();
// this.setPreferredSize(new Dimension(maxX,maxY));
// }
this.revalidate();
}
/**
* Funkcija postavlja boju u crvenu ako je automat trenutno neispravan za
* generiranje VHDL-a, inace se boja postavlja na crnu.
* @return color black or white
*/
private Color getOKColor() {
if (isOK) return Color.BLACK;
return Color.RED;
}
/**
* crta automat bez moguceg stanjaRada4
*
*/
private void nacrtajSklop(){
if(dataSet()){
checkOKness();
// resizeComponent();
Graphics2D g=(Graphics2D)img.getGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(getOKColor());
g.fillRect(0,0,img.getWidth(),img.getHeight());
g.setColor(Color.WHITE);
g.fillRect(3,3,img.getWidth()-6,img.getHeight()-6);
//crtanje stanja
if(stanjeZaDodati!=null){
g.setColor(stanjeZaDodati.boja);
g.fillArc(stanjeZaDodati.ox,stanjeZaDodati.oy,2*radijus,2*radijus,0,360);
g.setColor(Color.WHITE);
g.fillArc(stanjeZaDodati.ox+radijus/5,stanjeZaDodati.oy+radijus/5,2*(radijus-radijus/5),2*(radijus-radijus/5),0,360);
}
for(Stanje st:stanja){
g.setColor(st.boja);
g.fillArc(st.ox,st.oy,2*radijus,2*radijus,0,360);
g.setColor(Color.WHITE);
g.fillArc(st.ox+radijus/5,st.oy+radijus/5,2*(radijus-radijus/5),2*(radijus-radijus/5),0,360);
g.setColor(st.boja);
if(st.ime.equals(podatci.pocetnoStanje)){
g.drawLine(st.ox-17,st.oy+radijus,st.ox,st.oy+radijus);
int[] xP=new int[3];
int[] yP=new int[3];
setXYP(xP,yP,st);
g.fillPolygon(xP,yP,3);
}
//upis u stanja
String tekst=null;
if(podatci.tip.equals("Moore"))
tekst=new StringBuffer().append(st.ime).append("/").append(st.izlaz).toString();
else if (podatci.tip.equals("Mealy"))
tekst=new StringBuffer().append(st.ime).toString();
g.setFont(new Font("Helvetica", Font.BOLD, radijus/2));
FontMetrics fm= g.getFontMetrics();
int xString=st.ox+radijus-fm.stringWidth(tekst)/2;
int yString=st.oy+radijus+fm.getAscent()/2;
g.drawString(tekst,xString,yString);
g.setColor(Color.WHITE);
}
//crtanje prijelaza
for(Prijelaz pr:prijelazi){
Stanje iz=null;
Stanje ka=null;
for(Stanje stanje:stanja){
if(stanje.ime.equals(pr.iz)) iz=stanje;
if(stanje.ime.equals(pr.u)) ka=stanje;
}
nacrtajPrijelaz(iz, ka,pr);
}
//crtanje else prijelaza
for(Stanje st1:stanja)
for(Stanje st2:stanja)
if(st1.els.equalsIgnoreCase(st2.ime))nacrtajPrijelaz(st1,st2,null);
g.setColor(Color.BLACK);
String[] legendic=legenda.split("\n");
g.setFont(new Font("Arial", Font.BOLD, 10));
FontMetrics fm= g.getFontMetrics();
int odmak=legendic[0].length()>legendic[1].length()?
(legendic[0].length()>legendic[2].length()?fm.stringWidth(legendic[0]):fm.stringWidth(legendic[2])):
(legendic[1].length()>legendic[2].length()?fm.stringWidth(legendic[1]):fm.stringWidth(legendic[2]));
int xStr=img.getWidth()-odmak-10;
int yStr=fm.getHeight()+5;
g.drawString(legendic[0],xStr,yStr);
g.setFont(new Font("Arial", Font.PLAIN, 10));
fm= g.getFontMetrics();
yStr+=fm.getHeight();
g.drawString(legendic[1],xStr,yStr);
yStr+=fm.getHeight();
g.drawString(legendic[2],xStr,yStr);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
}
}
/**
* Postavlja isOK zastavicu na true ako je moguce napraviti
* VHDL iz trenutnog automata, inace false.
*
*/
private void checkOKness() {
if(stanja.size()==0||podatci.pocetnoStanje.equals(""))isOK=false;
else isOK=true;
}
private boolean dataSet() {
return (prijelazi!=null)&&(podatci!=null)&&(stanja!=null);
}
private void setXYP(int[] xp, int[] yp, Stanje st) {
xp[0]=st.ox;
xp[1]=st.ox-10;
xp[2]=st.ox-10;
yp[0]=st.oy+radijus;
yp[1]=st.oy+radijus+6;
yp[2]=st.oy+radijus-6;
}
/**
* metoda crta prijelaz iz stanja u stanje
* @param iz daje iz kojeg stanja
* @param ka daje u koje stanje
*/
private void nacrtajPrijelaz(Stanje iz, Stanje ka,Prijelaz pr){
//racunanje polozaja tocki potrebnih za crtanje prijelaza...
int x1,x2,y1,y2;
double fi=0;
if(ka.ox!=iz.ox){
fi=Math.atan((double)(ka.oy-iz.oy)/(ka.ox-iz.ox));
if(ka.ox<iz.ox)fi=Math.PI+fi;
}else{
fi=Math.PI/2;
if(ka.oy<iz.oy)fi=Math.PI+fi;
}
double strOdm=0.2;
if(pr==null)strOdm=0.5;
x1=ka.ox+radijus-(int)(Math.cos(fi+strOdm)*radijus);
y1=ka.oy+radijus-(int)(Math.sin(fi+strOdm)*radijus);
x2=iz.ox+radijus+(int)(Math.cos(fi-strOdm)*radijus);
y2=iz.oy+radijus+(int)(Math.sin(fi-strOdm)*radijus);
Graphics2D g=(Graphics2D) img.getGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
//boje
if(ka.equals(selektiran)||iz.equals(selektiran)) g.setColor(Color.ORANGE);
else g.setColor(Color.BLACK);
if(pr==null)g.setColor(Color.BLUE);
double l=radijus/2;
if(pr==null)l=radijus*2;
int x3=(int)(Math.abs(x2+(x1-x2)/2)+Math.cos(Math.PI/2-fi)*l);
int y3=(int)(Math.abs(y2+(y1-y2)/2)-Math.sin(Math.PI/2-fi)*l);
if(ka.equals(iz)){
l=radijus/2;
strOdm=0.7;
x1=ka.ox+radijus-(int)(Math.cos(fi+strOdm)*radijus);
y1=ka.oy+radijus-(int)(Math.sin(fi+strOdm)*radijus);
x2=iz.ox+radijus-(int)(Math.cos(fi-strOdm)*radijus);
y2=iz.oy+radijus-(int)(Math.sin(fi-strOdm)*radijus);
if(pr==null){
x1=ka.ox+radijus+(int)(Math.cos(fi+strOdm)*radijus);
y2=iz.oy+radijus+(int)(Math.sin(fi-strOdm)*radijus);
x3=(int)(Math.abs(x2+(x1-x2)/2)-7*l);
y3=(Math.abs(y2+(y1-y2)/2));
fi-=Math.PI/2;
strOdm=-0.3;
}
else{
x3=(Math.abs(x2+(x1-x2)/2));
y3=(int)(Math.abs(y2+(y1-y2)/2)-7*l);
strOdm=-0.2;
}
}
//crtanje prijelaza.....
QuadCurve2D curve=new QuadCurve2D.Double();
Point2D start, end ,control;
start = new Point2D.Double();
end = new Point2D.Double();
control = new Point2D.Double();
start.setLocation(x2,y2);
end.setLocation(x1,y1);
control.setLocation(x3,y3);
curve.setCurve(start,control,end);
g.draw(curve);
//upis podataka prijelaza
upisiPodatkePrijelaza(iz,ka,pr,x3,y3,fi);
//crtanje strijelica...
int l2=radijus/2;
int[] xstr = new int[3],ystr = new int[3];
xstr[1]=(int) (x1-l2*Math.cos(fi+0.3+strOdm));
ystr[1]=(int) (y1-l2*Math.sin(fi+0.3+strOdm));
xstr[2]=(int) (x1-l2*Math.cos(fi-0.3+strOdm));
ystr[2]=(int) (y1-l2*Math.sin(fi-0.3+strOdm));
xstr[0]=x1;ystr[0]=y1;
g.fillPolygon(xstr,ystr,3);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
}
/**
* ispis podataka prijelaza
* @param iz stanje iz kojeg prijelaz ide
* @param ka stanje ui koje prijelaz ide
* @param pr podatci o priejelazu
* @param x3 polaozaj korfinate x konetrolne tocke krivulje prijelaza
* @param y3 polozaj kordinate y kontrolne tocke krivulje prijelaza
* @param fi
*/
private void upisiPodatkePrijelaza(Stanje iz, Stanje ka, Prijelaz pr, int x3, int y3, double fi) {
Graphics2D g=(Graphics2D) img.getGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
String tekst="";
if(pr!=null)tekst=pr.toString();
else tekst="E";
g.setFont(new Font("Helvetica", Font.PLAIN, 2*radijus/5));
Color cl=g.getColor();
g.setColor(getMyColor(iz,ka));
FontMetrics fm=g.getFontMetrics();
int xtekst=x3-fm.stringWidth(tekst)/2;
int ytekst=y3+fm.getAscent()/2;
if(iz.equals(ka)) {
if(pr==null){
xtekst+=(int)(3*radijus/2.5);
ytekst-=(int)((double)fm.getAscent()/2*Math.cos(fi));
}
else ytekst+=(int)(3*radijus/2.2);
}else{
xtekst+=(int)((double)fm.stringWidth(tekst)/2*Math.sin(fi));
ytekst-=(int)((double)fm.getAscent()/2*Math.cos(fi));
if(pr==null)ytekst+=radijus*4/5;
}
g.drawString(tekst,xtekst,ytekst);
g.setColor(cl);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
}
/**
* Odreduje koje ce boje biti tekst prijelaza
* @param iz stanje iz kojeg se prelazi
* @param ka stanje u koje se prelazi
* @return boja koja nam treba
*/
private Color getMyColor(Stanje iz, Stanje ka) {
Color cl=Color.BLACK;
if(selektiran!=null)
if(selektiran.equals(iz)) cl=Color.RED;
else if(selektiran.equals(ka)) cl=Color.BLUE;
return cl;
}
// @Override
// public Dimension getPreferredSize() {
// int x,y;
// x=this.getWidth();
// y=this.getHeight();
// if(x==0)x=1;
// if(y==0)y=1;
// return new Dimension(x,y);
// }
/**
* Ova metoda provjerava dali je mis na podrucju selekcije prijelaza pr
* @param e MouseEvent koji se dogodio
* @param pr Prijelaz koji provjeravamo
* @return true ili false
*/
protected boolean jelSelektiran(MouseEvent e,Prijelaz pr){
Stanje ka=null,iz=null;
for(Stanje st:stanja){
if(st.ime.equals(pr.iz))iz=st;
if(st.ime.equals(pr.u))ka=st;
}
int x1,x2,y1,y2;
double fi=0;
if(ka.ox!=iz.ox){
fi=Math.atan((double)(ka.oy-iz.oy)/(ka.ox-iz.ox));
if(ka.ox<iz.ox)fi=Math.PI+fi;
}else{
fi=Math.PI/2;
if(ka.oy<iz.oy)fi=Math.PI+fi;
}
double strOdm=0.2;
x1=ka.ox+radijus-(int)(Math.cos(fi+strOdm)*radijus);
y1=ka.oy+radijus-(int)(Math.sin(fi+strOdm)*radijus);
x2=iz.ox+radijus+(int)(Math.cos(fi-strOdm)*radijus);
y2=iz.oy+radijus+(int)(Math.sin(fi-strOdm)*radijus);
Graphics2D g=(Graphics2D) img.getGraphics();
if(ka.equals(selektiran)||iz.equals(selektiran)) g.setColor(Color.ORANGE);
else g.setColor(Color.BLACK);
double l=radijus/2;
int x3=(int)(Math.abs(x2+(x1-x2)/2)+Math.cos(Math.PI/2-fi)*l);
int y3=(int)(Math.abs(y2+(y1-y2)/2)-Math.sin(Math.PI/2-fi)*l);
if(ka.equals(iz)){
strOdm=0.7;
x1=ka.ox+radijus-(int)(Math.cos(fi+strOdm)*radijus);
y1=ka.oy+radijus-(int)(Math.sin(fi+strOdm)*radijus);
x2=iz.ox+radijus-(int)(Math.cos(fi-strOdm)*radijus);
y2=iz.oy+radijus-(int)(Math.sin(fi-strOdm)*radijus);
x3=(Math.abs(x2+(x1-x2)/2));
y3=(int)(Math.abs(y2+(y1-y2)/2)-7*l);
strOdm=-0.2;
}
String tekst=pr.toString();
FontMetrics fm=g.getFontMetrics(new Font("Helvetica",Font.PLAIN,2*radijus/5));
int xtekst=x3-fm.stringWidth(tekst)/2;
int ytekst=y3+fm.getAscent()/2;
if(iz.equals(ka)) {
ytekst+=(int)(3*radijus/2.2);
}else{
xtekst+=(int)((double)fm.stringWidth(tekst)/2*Math.sin(fi));
ytekst-=(int)((double)fm.getAscent()/2*Math.cos(fi));
}
return e.getX()>xtekst&&e.getX()<xtekst+fm.stringWidth(tekst)&&e.getY()<ytekst&&e.getY()>ytekst-fm.getHeight();
}
/**
* Ova metoda provjerava dali je mis na podrucju selekcije zadanog stanja
* @param e MouseEvent koji se dogodio
* @param st Stanje za koje provjeravamo
* @return true ili false
*/
protected boolean jelSelektiran(MouseEvent e,Stanje st){
int x1=e.getX();
int y1=e.getY();
return (Math.sqrt(Math.pow(x1-st.ox-radijus,2)+Math.pow(y1-st.oy-radijus,2)))<radijus;
}
public void setStanjeRada(int stanjeRada) {
stanjeZaDodati=null;
prijelazZaDodati=null;
repaint();
this.stanjeRada = stanjeRada;
if(stanjeRada==2)stanjeZaDodati=new Stanje();
/* if(stanjeRada==2){
boolean zastavica=true;
while(zastavica){
stanjeZaDodati=new Stanje(podatci,this);
if(stanjeZaDodati.ime==null){
this.stanjeRada=1;
stanjeZaDodati=null;
zastavica=false;
}
boolean z2=true;
if(zastavica)
for(Stanje st:stanja) if(st.equals(stanjeZaDodati))z2=false;
if(z2)zastavica=false;
else{
int x=JOptionPane.showConfirmDialog(this,
"Unjeli ste ime stanja koje vec postoji\nZelite li pokusat ponovo?",
"Upozorenje",
JOptionPane.YES_NO_OPTION,JOptionPane.WARNING_MESSAGE);
if(x==JOptionPane.NO_OPTION){
this.stanjeRada=1;
stanjeZaDodati=null;
zastavica=false;
}
}
}
}*/
if(stanjeRada==3)prijelazZaDodati=new Prijelaz();
}
public void brisiPrijelaz(Prijelaz pr) {
prijelazi.remove(pr);
repaint();
}
public void brisiStanje(Stanje st) {
HashSet<Prijelaz> pomocni=new HashSet<Prijelaz>();
for(Prijelaz pr:prijelazi){
if(st.ime.equals(pr.iz)||st.ime.equals(pr.u))pomocni.add(pr);
}
prijelazi.removeAll(pomocni);
stanja.remove(st);
}
public void editorPrijelaza(Prijelaz pr) {
final Prijelaz pr2=pr;
JButton add=new JButton(bundle.getString(LanguageConstants.EDITOR_ADD));
JButton delete=new JButton(bundle.getString(LanguageConstants.EDITOR_DELETE));
JLabel poruka=new JLabel(bundle.getString(LanguageConstants.EDITOR_LIST)+":");
final DefaultListModel listam=new DefaultListModel();
for(String st:pr2.pobudaIzlaz)listam.addElement(st);
final JList list=new JList(listam);
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.setLayoutOrientation(JList.VERTICAL);
list.setVisibleRowCount(-1);
list.setSelectedIndex(0);
JScrollPane listScroller = new JScrollPane(list);
listScroller.setPreferredSize(new Dimension(250, 80));
JPanel panel=new JPanel(new BorderLayout());
panel.add(listScroller,BorderLayout.CENTER);
JPanel panel2=new JPanel(new GridLayout(2,1));
panel2.add(add);
panel2.add(delete);
panel.add(panel2,BorderLayout.EAST);
panel.add(poruka,BorderLayout.NORTH);
add.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
Prijelaz pomocni=new Prijelaz();
String str=pomocni.editPrijelaz2(podatci,AutoDrawer.this,bundle);
if(str!=null){
pomocni.iz=pr2.iz;
pomocni.pobudaIzlaz.add(str);
if(listam.indexOf(str)==-1&&!pomocni.equals2(pomocni,prijelazi)){
listam.addElement(str);
pr2.pobudaIzlaz.add(str);
} else pr2.porukaNeDodaj(AutoDrawer.this,bundle);
}
}
});
String ok_option=bundle.getString(LanguageConstants.DIALOG_BUTTON_OK);
String cancel_option=bundle.getString(LanguageConstants.DIALOG_BUTTON_CANCEL);
String[] options={ok_option,cancel_option};
delete.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
if(list.getSelectedIndex()>-1)
if (listam.size()>0) {
String pom=(String)list.getSelectedValue();
listam.remove(list.getSelectedIndex());
pr2.pobudaIzlaz.remove(pom);
}
//else JOptionPane.showMessageDialog(AutoDrawer.this,bundle.getString(LanguageConstants.EDITOR_MESSAGE));
}
});
JOptionPane optionPane=new JOptionPane(panel,JOptionPane.PLAIN_MESSAGE,JOptionPane.OK_CANCEL_OPTION,null,options,options[0]);
JDialog dialog=optionPane.createDialog(this,bundle.getString(LanguageConstants.EDITOR_TITLE));
dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
dialog.setVisible(true);
Object selected=optionPane.getValue();
if(selected.equals(options[0])){
if(pr2.pobudaIzlaz.size()>0)
pr=pr2;
else prijelazi.remove(pr);
repaint();
}
}
/**
* niz funkcija koje sreduju resize i sl
* @param x
* @param y
*/
protected void pomjeriSliku(int x, int y) {
////TODO //if(x+radijus>AutoDrawer.this.getWidth())AutoDrawer.this.setPreferredSize(new Dimension(x+radijus,AutoDrawer.this.getHeight()));
// //if(y+radijus>AutoDrawer.this.getHeight())AutoDrawer.this.setPreferredSize(new Dimension(AutoDrawer.this.getWidth(),y+radijus));
//
// if(x<3.3*radijus||y<3.3*radijus) moveAll(x,y); //TODO i tu je odmak!!!
// AutoDrawer.this.revalidate();
// }
//
// private void moveAll(int x, int y) {
// final int odmak=(int) (3.3*radijus);
// for(Stanje s:stanja){
// s.ox-=(x<odmak?x-odmak:0);
// s.oy-=(y<odmak?y-odmak:0);
// }
// if(x<odmak)AutoDrawer.this.setPreferredSize(new Dimension(AutoDrawer.this.getWidth()-x+odmak,AutoDrawer.this.getHeight()));
// if(y<odmak)AutoDrawer.this.setPreferredSize(new Dimension(AutoDrawer.this.getWidth(),AutoDrawer.this.getHeight()-y+odmak));
}
//****************************NESTED CLASESS****************************************
/**
* Klasa koja se bavi pomicanjem misa i selektiranih elemenata. Implementira MouseMotionListener
* @author ddelac
*
*/
protected class Mouse2 implements MouseMotionListener{
/**
* Funkcija propisana suceljem, obavlja dio drag&drop funkcionalnosti
*/
public void mouseDragged(MouseEvent e) {
if(pressed){
//pomjeriSliku(e.getX(),e.getY());
editor.setModified(true);
selektiran.ox=e.getX()-radijus;
selektiran.oy=e.getY()-radijus;
/*if(selektiran.ox>img.getWidth()-2*radijus) selektiran.ox=img.getWidth()-2*radijus;
if(selektiran.ox<0)selektiran.ox=0;
if(selektiran.oy>img.getHeight()-2*radijus) selektiran.oy=img.getHeight()-2*radijus;
if(selektiran.oy<0)selektiran.oy=0;*/
resizeComponent();
repaint();
}
}
/**
* Funkcija propisana suceljem, ne radi nista...
*/
public void mouseMoved(MouseEvent e) {
if(stanjeRada==2){
stanjeZaDodati.ox=e.getX()-radijus;
stanjeZaDodati.oy=e.getY()-radijus;
if(stanjeZaDodati.ox>img.getWidth()-2*radijus) stanjeZaDodati.ox=img.getWidth()-2*radijus;
if(stanjeZaDodati.ox<0)stanjeZaDodati.ox=0;
if(stanjeZaDodati.oy>img.getHeight()-2*radijus) stanjeZaDodati.oy=img.getHeight()-2*radijus;
if(stanjeZaDodati.oy<0)stanjeZaDodati.oy=0;
repaint();
}
if(stanjeRada==4){
resizeComponent();
nacrtajSklop(e.getX(),e.getY());
}
}
}
protected class Mouse implements MouseListener{
/**
* Funkcija propisana suceljem, ne radi nista...
*/
public void mouseClicked(MouseEvent e) {
if(stanjeRada==1&&e.getButton()==MouseEvent.BUTTON3){
for(Stanje st:stanja)
if(jelSelektiran(e,st)){
st.editStanje2(podatci,AutoDrawer.this,bundle);
editor.setModified(true);
repaint();
break;
}
for(Prijelaz pr:prijelazi)
if(jelSelektiran(e,pr)){
editorPrijelaza(pr);
editor.setModified(true);
break;
}
}
if(stanjeRada==2){
if (e.getButton()==MouseEvent.BUTTON1){
stanjeZaDodati.boja=Color.BLACK;
boolean zastavica=true;
boolean dodaj=true;
while(zastavica){
stanjeZaDodati.editStanje(podatci,AutoDrawer.this,bundle);
if(stanjeZaDodati.ime==null){
stanjeRada=2;
dodaj=false;
stanjeZaDodati=null;
stanjeZaDodati=new Stanje();
zastavica=false;
}
boolean z2=true;
if(zastavica){
for(Stanje st:stanja) if(st.equals(stanjeZaDodati))z2=false;
if(!new NameFormatConstraintValidator().isValid("st_"+stanjeZaDodati.ime))z2=false;
}
if(z2&&(!listaSignala.contains("st_"+stanjeZaDodati.ime.toLowerCase())))zastavica=false;
else{
String[] options={bundle.getString(LanguageConstants.DIALOG_BUTTON_YES),
bundle.getString(LanguageConstants.DIALOG_BUTTON_NO)};
JOptionPane pane= new JOptionPane(bundle.getString(LanguageConstants.DIALOG_MESSAGE_STATEEXISTS),
JOptionPane.WARNING_MESSAGE,JOptionPane.YES_NO_OPTION,null,options,options[0]);
JDialog dialog=pane.createDialog(AutoDrawer.this,bundle.getString(LanguageConstants.DIALOG_TITLE_WARNING));
dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
dialog.setVisible(true);
Object reza=pane.getValue();
if(reza.equals(options[1])){
dodaj=false;
stanjeRada=2;
stanjeZaDodati=null;
stanjeZaDodati=new Stanje();
zastavica=false;
}
}
}
if(dodaj){
stanjeZaDodati.els=stanjeZaDodati.ime;
stanjeZaDodati.eIz="0";
stanja.add(stanjeZaDodati);
editor.setModified(true);
}
stanjeRada=1;
stanjeZaDodati=null;
setStanjeRada(2);
resizeComponent();
repaint();
}
}
if(stanjeRada==3&&e.getButton()==MouseEvent.BUTTON1){
for(Stanje st:stanja)
if(jelSelektiran(e,st)){
prijelazZaDodati.iz=st.ime;
stanjeRada=4;
break;
} }
else if(stanjeRada==4&&e.getButton()==MouseEvent.BUTTON1)
for(Stanje sta:stanja)
if(jelSelektiran(e,sta)){
prijelazZaDodati.u=sta.ime;
prijelazZaDodati.editPrijelaz(podatci,AutoDrawer.this,bundle);
if(!prijelazZaDodati.pobudaIzlaz.first().split("/")[0].equalsIgnoreCase("ELSE")){
boolean test=true;
for(Prijelaz pr:prijelazi)
if(pr.equals(prijelazZaDodati)){
test=false;
pr.dodajPodatak(prijelazZaDodati,prijelazi);
}
if(test&&prijelazZaDodati.pobudaIzlaz.size()!=0){
if(!prijelazZaDodati.equals2(prijelazZaDodati,prijelazi)){
prijelazi.add(prijelazZaDodati);
}else prijelazZaDodati.porukaNeDodaj(AutoDrawer.this,bundle);
}
}else{
for(Stanje st:stanja)
if(st.ime.equalsIgnoreCase(prijelazZaDodati.iz)){
st.els=prijelazZaDodati.u;
if(podatci.tip.equalsIgnoreCase("Mealy"))
st.eIz=prijelazZaDodati.pobudaIzlaz.first().split("/")[1];
}
}
prijelazZaDodati=null;
prijelazZaDodati=new Prijelaz();
stanjeRada=3;
editor.setModified(true);
repaint();
break;
}
if(stanjeRada==5){
for(Stanje st:stanja)
if (jelSelektiran(e,st)) {
if(st.ime.equals(podatci.pocetnoStanje))podatci.pocetnoStanje="";
brisiStanje(st);
editor.setModified(true);
repaint();
break;
}
for(Prijelaz pr:prijelazi)
if(jelSelektiran(e,pr)){
brisiPrijelaz(pr);
editor.setModified(true);
repaint();
break;
}
}
if(stanjeRada==6&&e.getButton()==MouseEvent.BUTTON1){
for(Stanje st:stanja)
if(jelSelektiran(e,st)){
if(!podatci.pocetnoStanje.equals(st.ime)){
podatci.pocetnoStanje=st.ime;
editor.setModified(true);
}
break;
}
repaint();
}
/*if(e.getButton()==MouseEvent.BUTTON3){
stanjeZaDodati=null;
prijelazZaDodati=null;
stanjeRada=1;
nacrtajSklop();
}*/
}
/**
* Funkcija propisana suceljem, obavlja dio drag&drop funkcionalnosti
*/
public void mousePressed(MouseEvent e) {
if(stanjeRada==1)
if(e.getButton()==MouseEvent.BUTTON1 )
for(Stanje st:stanja)
if(jelSelektiran(e,st)){
st.boja=Color.GREEN;
pressed=true;
selektiran=st;
repaint();
break;
}
}
/**
* Funkcija propisana suceljem, obavlja dio drag&drop funkcionalnosti
*/
public void mouseReleased(MouseEvent e) {
if(pressed){
pomjeriSliku(e.getX(),e.getY());
/*if(e.getX()>AutoDrawer.this.getWidth())AutoDrawer.this.setSize(e.getX(),AutoDrawer.this.getHeight());
if(e.getY()>AutoDrawer.this.getHeight())AutoDrawer.this.setSize(AutoDrawer.this.getWidth(),e.getY());
if(e.getX()<0||e.getY()<0) moveAll(e.getX(),e.getY());
*/
/*if(selektiran.ox>img.getWidth()-2*radijus) selektiran.ox=img.getWidth()-2*radijus;
if(selektiran.ox<0)selektiran.ox=0;
if(selektiran.oy>img.getHeight()-2*radijus) selektiran.oy=img.getHeight()-2*radijus;
if(selektiran.oy<0)selektiran.oy=0;*/
selektiran.boja=Color.BLACK;
selektiran=null;
resizeComponent();
repaint();
pressed=false;
}
podatci.sirina=AutoDrawer.this.getWidth();
podatci.visina=AutoDrawer.this.getHeight();
}
/**
* nis ne radi...
*/
public void mouseEntered(MouseEvent e) {}
/**
* nis ne radi...
*/
public void mouseExited(MouseEvent e) {}
}
public AUTPodatci getPodatci() {
return podatci;
}
public void setResourceBundle(ResourceBundle bundle) {
this.bundle=bundle;
}
public void dataChange() {
JTextField tip=new JTextField(podatci.tip);
tip.setEditable(false);
tip.setBorder(BorderFactory.createTitledBorder(bundle.getString(LanguageConstants.DIALOG_TEXT_TYPE)));
String[] polje=podatci.interfac.split("\n");
final DefaultListModel listam=new DefaultListModel();
for(String st:polje)listam.addElement(st);
final JList list=new JList(listam);
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.setLayoutOrientation(JList.VERTICAL);
list.setVisibleRowCount(-1);
list.setSelectedIndex(0);
JScrollPane listScroller = new JScrollPane(list);
list.setBorder(BorderFactory.createTitledBorder(bundle.getString(LanguageConstants.DIALOG_TEXT_SIGNALS)));
listScroller.setPreferredSize(new Dimension(250, 80));
JButton change=new JButton("Edit signal");
change.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
String pom=(String) list.getSelectedValue();
String[] polj=pom.split(" ");
polj[0]=editSignal(polj[0]);
StringBuffer buf=new StringBuffer().append(polj[0]).append(" ").append(polj[1]).append(" ")
.append(polj[2]);
if (polj[2].equalsIgnoreCase("Std_Logic_vector"))buf.append(" ").append(polj[3])
.append(" ").append(polj[4]);
listam.set(list.getSelectedIndex(),buf.toString());
}
private String editSignal(String string) {
String[] options={bundle.getString(LanguageConstants.DIALOG_BUTTON_OK),
bundle.getString(LanguageConstants.DIALOG_BUTTON_CANCEL)
};
JTextField name=new JTextField(string);
name.setBorder(BorderFactory.createTitledBorder(bundle.getString(LanguageConstants.DIALOG_TEXT_SIGNALNAME)));
JOptionPane optionPane=new JOptionPane(name,JOptionPane.QUESTION_MESSAGE,JOptionPane.OK_CANCEL_OPTION,null,options,options[0]);
JDialog dialog=optionPane.createDialog(AutoDrawer.this,bundle.getString(LanguageConstants.DIALOG_TITLE_MACHINEDATA));
dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
dialog.setVisible(true);
Object selected=optionPane.getValue();
if(selected.equals(options[1])) return string;
String st=name.getText();
if((listaSignala.contains(st.toLowerCase())||!new NameFormatConstraintValidator().isValid(st))&&!st.equalsIgnoreCase(string)){
String[] options2={bundle.getString(LanguageConstants.DIALOG_BUTTON_YES),
bundle.getString(LanguageConstants.DIALOG_BUTTON_NO)};
JOptionPane pane= new JOptionPane(bundle.getString(LanguageConstants.DIALOG_MESSAGE_SIGNALEXISTS),
JOptionPane.WARNING_MESSAGE,JOptionPane.YES_NO_OPTION,null,options2,options[0]);
JDialog dialog2=pane.createDialog(AutoDrawer.this,bundle.getString(LanguageConstants.DIALOG_TITLE_WARNING));
dialog2.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
dialog2.setVisible(true);
Object reza=pane.getValue();
if(reza.equals(options[1])){
return string;
}
return editSignal(string);
}
listaSignala.remove(string);
listaSignala.add(st);
return st;
}
});
JPanel panel=new JPanel();
panel.setLayout(new BorderLayout());
panel.add(tip,BorderLayout.NORTH);
panel.add(list,BorderLayout.CENTER);
panel.add(change,BorderLayout.SOUTH);
String[] options={bundle.getString(LanguageConstants.DIALOG_BUTTON_OK),
bundle.getString(LanguageConstants.DIALOG_BUTTON_CANCEL)
};
JOptionPane optionPane=new JOptionPane(panel,JOptionPane.PLAIN_MESSAGE,JOptionPane.OK_CANCEL_OPTION,null,options,options[0]);
JDialog dialog=optionPane.createDialog(this,bundle.getString(LanguageConstants.DIALOG_TITLE_MACHINEDATA));
dialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
dialog.setVisible(true);
Object selected=optionPane.getValue();
if(selected.equals(options[0])) {
StringBuffer buf=new StringBuffer();
for(Object str:listam.toArray())buf.append((String)str).append("\n");
buf.deleteCharAt(buf.length()-1);
podatci.interfac=buf.toString();
parseLegend();
repaint();
}
}
/*public void setMinXY(int minX,int minY) {
this.minX = minX;
this.minY=minY;
}*/
}