/**
 *  File neve : Viewpanel.java (Viewpanel osztaly)
 *
 *  Leírás : Ez az osztály a Viewpanel amin a grafikus műveletek
 *           történnek a 'graf' típusú 'epulet' egyed segítségével.
 *           Az 'epulet' egyed segítségével teszi a gráfot vizuálisan is
 *           láthatóvá. A konstruktor paraméterei : 
 *           'parent' : a szülő ScrollPane,
 *           'filenev' : a file-nak a neve amelyből a gráfot töltjük be
 *           ha üres vagy nem létezik akkor új gráfot hozunk létre.
 *
 *  Készítette Takács Mihály 1998.06. 
 */

import java.util.*;
import java.awt.event.*;
import java.awt.*;

class Viewpanel extends Panel implements MouseListener, ActionListener,
				    MouseMotionListener {
  ScrollPane parent;  // A befoglaló ScrollPane
  PopupMenu popup;  // Terminál felpattanó menüje
  MenuItem tulajdonsag,utvonal;  // Felpattanó menühoz
  boolean utkerelem=false;   // Ha útvonalat kér akkor lesz igaz
  graf epulet;    // Maga a gráf amit vizuálisan is megjelenitünk
  lista csucsok;  // A gráf összes csúcsa egy vektorban

  Viewpanel(ScrollPane parent,String filenev) {
    if (!beolvas(filenev)) {  // Rossz beolvasás esetén
      setEnabled(false);
      setSize(5,5);
      ((MenMenu)parent.getParent()).csoportok.setEnabled(false);
      ((MenMenu)parent.getParent()).bezar.setEnabled(false);
      Uzenet uzen=new Uzenet((Frame)parent.getParent(),"Hiba","HIBA : Nem letezo file vagy rossz file formatum!",Uzenet.hiba);  // Üzenő ablak
      epulet=new graf("semmi");
    } else {
      setSize(2000,1000);
    }
    this.parent=parent;
    popup=new PopupMenu();
      tulajdonsag=new MenuItem("Tulajdonsag");
      tulajdonsag.addActionListener(this);
      popup.add(tulajdonsag);
      utvonal=new MenuItem("Utvonal");
      utvonal.addActionListener(this);
      popup.add(utvonal);
    add(popup);
    addMouseListener(this);
    addMouseMotionListener(this);

    csucsok=epulet.csucsok();  // csúcsok a listában (elég most az elején frissíteni, úgy sem lehet változtatni a gráfot)
  }

  Image offscreen;  // Pufferelt rajzoláshoz
  Dimension offscreensize;
  Graphics offgraphics;
  
  final Color selectColor = Color.pink;
  final Color lineColor = Color.black;
  final Color csucsColor = new Color(250, 220, 100);

  public void paintcsucs(Graphics g, csucs n, FontMetrics fm) {
    int x = n.x;
    int y = n.y;
    g.setColor(n.select ? selectColor : csucsColor); // Útvonalban van?
    int w = fm.stringWidth(n.neve)+10;
    int h = fm.getHeight()+4;
    n.dx = w;
    n.dy = h;
    g.fillRect(x,y,w,h);
    g.setColor(Color.black);
    g.drawRect(x,y,w-1,h-1);
    g.drawString(n.neve,x+5,y+2+fm.getAscent());
  }

  public void update(Graphics g) {
    setSize(2000,1000);
    Dimension d=size();
    csucs aktualis,rakovetkezo;

    if ((offscreen==null) || /* Ha még nem volt vagy át volt méretezve */
	(d.width!=offscreensize.width) || (d.height!=offscreensize.height)) {
      offscreen = createImage(d.width, d.height);
      offscreensize = d;
      offgraphics = offscreen.getGraphics();
      offgraphics.setFont(getFont());
    }
    offgraphics.setColor(getBackground());  // Offscreen törlése
    offgraphics.fillRect(0, 0, d.width, d.height);
    /*
     * Végig megyünk az összes csúcson és a rákövetkező csúcsaival összekötjük
     * őt. Vagyis a szakaszok kirajzolása. 
     */
    csucsok=epulet.csucsok();
    for (Enumeration e=csucsok.elements(); e.hasMoreElements(); ) {
      aktualis=(csucs)e.nextElement();
      if (!aktualis.torolt && (aktualis.x!=csucs.valotlan)) {
	for (Enumeration f=aktualis.kovetkezo.elements();
	     f.hasMoreElements(); ) { // A rákövetkező csúcsok sorban
	  rakovetkezo=(csucs)f.nextElement();
	  if (!rakovetkezo.torolt && (rakovetkezo.x!=csucs.valotlan)) {
	             /* A szakaszok kirajzolása */
	    /* A csúcsok közepének koordinátai */
	    int kozepx1 = aktualis.x+aktualis.dx/2;
	    int kozepy1 = aktualis.y+aktualis.dy/2;
	    int kozepx2 = rakovetkezo.x+rakovetkezo.dx/2;
	    int kozepy2 = rakovetkezo.y+rakovetkezo.dy/2;
	    offgraphics.setColor(lineColor); // A szakasz megrajzolása
	    offgraphics.drawLine(kozepx1,kozepy1,kozepx2,kozepy2);
	    /* A nyíl kirajzolása a szakaszra. */
	    int Xtav=kozepx2-kozepx1; // A szakasz vektor x koordinátája
	    int Ytav=kozepy2-kozepy1; // A szakasz vektor y koordinátája
	    double len=Math.abs(Math.sqrt(Xtav*Xtav+Ytav*Ytav)); //szakaszhossz
	    if (len>10) {  // Csak ekkor rajzolunk nyílat
	      double arany=5/len;  // A nyíl hossza mindig 5 egység
	      int vx=(int)(Xtav*arany); //Ez a nyíl helyét mutatja
	      int vy=(int)(Ytav*arany);
	      // Oda nyíl
	      int szakaszkozepex=(kozepx2+kozepx1)/2; //A szakasz felező
	      int szakaszkozepey=(kozepy2+kozepy1)/2; //    pontja
	      offgraphics.drawLine(szakaszkozepex+vx*2, szakaszkozepey+vy*2,
				   szakaszkozepex+vy  , szakaszkozepey-vx);
	      offgraphics.drawLine(szakaszkozepex+vx*2, szakaszkozepey+vy*2,
				   szakaszkozepex-vy  , szakaszkozepey+vx);
	    }
	  }
	}
      }
    }
    /* A csúcsok kirajzolása */
    FontMetrics fm = offgraphics.getFontMetrics();
    for (Enumeration e=csucsok.elements(); e.hasMoreElements(); ) {
      aktualis=(csucs)e.nextElement();
      if (aktualis.x!=csucs.valotlan) {
	paintcsucs(offgraphics, aktualis, fm);
      }
    }
    g.drawImage(offscreen, 0, 0, null);  // Képernyőváltás
  }
  
     /* MouseMotionListener interfész implementálása */

  int duplaklikk=0;  // A duplakattintás számolásához a mouseClicked fv-ben
  public void mouseMoved(MouseEvent evt) {duplaklikk=0;}

  public void mouseDragged(MouseEvent evt) {}

     /* MouseListener interfész implementálása */
  Point TermPosition=new Point(0,0);  // A terminál pozíciója (esemény helye)
  csucs popupselect=null;  // Melyik csúcs felett nyomtunk popup menüt
  csucs honnan=null, hova=null;   // útvonal: honnan, hova
  Vector ut;                      // maga az útvonal
  int lepesek=0;   // Az útvonal meghatározásanak lépesei

  public void mouseClicked(MouseEvent evt) {
    csucs aktualis;

    TermPosition=evt.getPoint();
    try {
      for (Enumeration e=ut.elements(); e.hasMoreElements(); ) {
	aktualis=(csucs)e.nextElement();
	aktualis.select=false;   // Szürke színnel kirajzolás törlése
      }
    } catch (NullPointerException err) {}  // ha nincs út
    if (utkerelem) {  // Útvonal kérelem, most jelöli ki a csúcskat
      if (lepesek==0) {
	if ((honnan=epulet.Keres(TermPosition.x,TermPosition.y))==null) {
	  utkerelem=false;    // Útkeresés stornozva, nem csúcson klikkelt
	  lepesek=0;
	} else { lepesek++; }  // Jöhet a következő lépés
      } else if (lepesek==1) {
	if ((hova=epulet.Keres(TermPosition.x,TermPosition.y))==null) {
	  utkerelem=false;    // Útkeresés stornozva, nem csúcson klikkelt
	  lepesek=0;
	} else {   // Na mostmár megvan mind a két csúcs
	  try {  // Lehet hogy nincs út
	    ut=epulet.BF(honnan,hova);
	    for (Enumeration e=ut.elements(); e.hasMoreElements(); ) {
	      aktualis=(csucs)e.nextElement();
	      aktualis.select=true;       // Kirajzoljuk szürke színnel
	    }
	  } catch (NullPointerException err) {  // nincs út
	    Uzenet uzen=new Uzenet((Frame)parent.getParent(),"Üzenet","A ket csucs kozott nincs iranyitott ut.",Uzenet.hiba);  // Üzenő ablak
	  }
	  lepesek=0;
	  utkerelem=false;
	  honnan=null;  hova=null;
	}
      }
    } else if ((++duplaklikk)%2==0) {
      duplaklikk=0;
      if ((popupselect=epulet.Keres(TermPosition.x,TermPosition.y))!=null) {
	actionPerformed(new ActionEvent(tulajdonsag,ActionEvent.ACTION_PERFORMED,"Tulajdonsag",0));
      }
    }
    repaint();
  }

  public void mousePressed(MouseEvent evt) {
    if (evt.isPopupTrigger()) {  // Ha PopupMenu-t aktivizáltunk
      TermPosition=evt.getPoint();
      if ((popupselect=epulet.Keres(TermPosition.x,TermPosition.y))==null) {
	// Ha nem csúcson klikkeltünk
	tulajdonsag.setEnabled(false);
      } else {  // Csúcson klikkeltünk
	tulajdonsag.setEnabled(true);
      }
      popup.show(this,TermPosition.x,TermPosition.y); //PopupMenu
    }
    repaint();
  }

  public void mouseReleased(MouseEvent evt) {}
  public void mouseEntered(MouseEvent evt) {repaint();}
  public void mouseExited(MouseEvent evt) {}

	/* ActionListener interfész implementálása a PopupMenu-khöz */
  public void actionPerformed(ActionEvent evt) {
    Object s=evt.getSource();  // Visszaadja honnan jött az esemény
    /* A popup menü menüpontjai */
    if (s.equals(tulajdonsag )) {
      TermView regiterm=new TermView((Frame)parent.getParent(),
	 this,"Terminál tulajdonságai",TermPosition,popupselect.neve,
	 popupselect.azonosito,popupselect.kovetkezok(),popupselect.csoport,
	 popupselect.tol,popupselect.ig);
                   // A második szülő a Frame (MenMenu)
      regiterm.show();
      if (regiterm.utvonalkerelem) {
	actionPerformed(new ActionEvent(utvonal,ActionEvent.ACTION_PERFORMED,"Utvonal",0));
      }
    } else if (s.equals(utvonal)) {
      Uzenet uzen=new Uzenet((Frame)parent.getParent(),"Üzenet","Honnan hova akar eljutni? Klikkeljen a ket csucsra.",Uzenet.hiba);  // Üzenő ablak
      utkerelem=true;
    }
    repaint();
  }

    /**
     *  Ezzel frissíti az adatokat a TermView ablak
     */
  public csucs getcsucs(String azonosito) {
    return epulet.Keres(azonosito);
  }
    /** 
     * Ezen keresztül tud beolvasni a MenMenu egyed (a szülő)
     **/
  public boolean beolvas(String filenev) {
    boolean l;
    epulet=new graf();
    l=epulet.beolvas(filenev);
    return l;
  }
}
