package view;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.math.BigDecimal;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import model.Line;
import model.Station;
import controller.Controller;
/**
* La classe <b>PersonnalPanel</b> hérite de JPanel et implémente ActionListener
* ainsi que MouseWheelListener. Elle permet de créer un panel personnalisé
*
* @version 1.0
* @author Pierre Facq
* @author Alan Grente-Lequertier
* @author Alexandre Paris-Vergne
* @author Thomas Sileghem
*
*/
public class PersonnalPanel extends JPanel implements ActionListener,
MouseWheelListener {
private static final long serialVersionUID = 1L;
Controller controller;
double scalingX;
double scalingY;
double ratioX = 1.0, ratioY = 1.0;
double mouseWheelValue = 0;
double xPos = 0, yPos = 0;
double xMid, yMid;
double longMid, latMid;
double xDeb, yDeb;
double distanceX, distanceY;
double xDec = 0, yDec = 0;
boolean init;
int taille;
int x;
int y;
double maxMin[][];
boolean backGroundMapEnable;
String urlBackGroundImage;
ImageIcon backGroundImage;
boolean mapViewEnabled;
String mapType="map";
boolean toRecalculate;
/**
* Initialise un PersonnalPanel qui permet de zoomer sur son contenu.
*
* @param pController
* le controlleur par défaut de l'application
*/
public PersonnalPanel(Controller pController) {
super();
this.controller = pController;
this.backGroundImage = new ImageIcon();
mapViewEnabled = true;
init = true;
maxMin = this.controller.getMaxMinCoordinate();
// Calcule la distance en le point le plus à droite
// et le point le plus à gauche
distanceX = maxMin[1][0] - maxMin[0][0];
// Calcule la distance en le point le plus en haut
// et le point le plus en bas
distanceY = maxMin[1][1] - maxMin[0][1];
x = this.getWidth();
y = this.getHeight();
// Coordonnées du milieu
xMid = x / 2;
yMid = y / 2;
taille = Math.min(x, y) / 100;
xPos = xMid;
yPos = yMid;
toRecalculate=true;
// En cas d'action sur la molette de la souris
this.addMouseWheelListener(new MouseWheelListener() {
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
mouseWheelValue -= e.getPreciseWheelRotation() / 10;
xPos = e.getX();
yPos = e.getY();
toRecalculate=true;
controller.repaintAllWindows();
}
});
// En cas d'action de la souris autre qu'un roulement de la molette
this.addMouseListener(new MouseListener() {
/**
* En cas de clic sur la souris
*/
@Override
public void mouseClicked(final MouseEvent mouseEvt) {
// Si le clic est un clic droit, un menu apparaît
// Il permet d'ajouter une station à l'endroit où le clic
// a été effectué
if (mouseEvt.getButton() == MouseEvent.BUTTON3) {
JPopupMenu popUp = new JPopupMenu();
JMenuItem insert = new JMenuItem("Ajouter station");
insert.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
InsertStations insertStations = new InsertStations(
controller);
int taille = Math.min(x, y) / 100;
double longitude = longMid
- (xMid - mouseEvt.getX()) / scalingX;
double latitude = latMid - (mouseEvt.getY() - yMid)
/ scalingY;
insertStations.setCoordinate(longitude, latitude);
insertStations.createPopup();
insertStations.confirmPopup();
((JPanel) mouseEvt.getSource()).requestFocus();
}
});
popUp.add(insert);
popUp.show(mouseEvt.getComponent(), mouseEvt.getX(),
mouseEvt.getY());
}
// Si c'est un clic gauche et qu'il y a une station à placer,
// place la station à l'endroit du clic
else if (mouseEvt.getButton() == MouseEvent.BUTTON1) {
InsertStations station = controller.getStationToPlace();
if (station != null) {
int taille = Math.min(x, y) / 100;
double longitude = ((mouseEvt.getX() - taille / 2) / scalingX)
+ maxMin[0][0];
double latitude = ((mouseEvt.getY() + 3 * (taille / 2) - y) / -scalingY)
+ maxMin[0][1];
station.setCoordinate(longitude, latitude);
station.confirmPopup();
controller.setStationToPlace(null);
}
}
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
});
}
/**
* Dessine les éléments du panel
*/
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
this.removeAll();
x = this.getWidth();
y = this.getHeight();
xMid = x / 2;
yMid = y / 2;
if (init) {
xPos = xMid;
yPos = yMid;
init = false;
}
g.setColor(new Color(0xFF, 0x0, 0x0));
Station stations[] = controller.getStations();
int size = stations.length;
Line lines[] = controller.getLines();
int lsize = lines.length;
taille = Math.min(x, y) / 100;
// En cas d'action sur la molette de la souris, actualise l'affichage
// en zoomant ou dézoomant
if (this.mouseWheelValue <= 0.05 || this.mouseWheelValue >= -0.05) {
xDeb = maxMin[0][0];
yDeb = maxMin[0][1];
}
if (this.mouseWheelValue < 0.15) {
scalingX = Math.abs((x - taille * 2)
/ (distanceX - this.mouseWheelValue));
scalingY = Math.abs((y - taille * 2)
/ (distanceY - this.mouseWheelValue));
} else {
scalingX = Math.abs((x - taille * 2)
/ (distanceX / (this.mouseWheelValue * 10)));
scalingY = Math.abs((y - taille * 2)
/ (distanceY / (this.mouseWheelValue * 10)));
}
if(toRecalculate){
xDec = (xPos - xMid) / scalingX + xDec;
yDec = (yMid - yPos) / scalingY + yDec;
toRecalculate=false;
}
longMid = ((xMid /*- taille /2*/) / scalingX) + xDeb
- (x / scalingX - distanceX) / 2 + xDec;
latMid = ((yMid /* + 3 * (taille / 2) */- y) / -scalingY) + yDeb
- (y / scalingY - distanceY) / 2 + yDec;
// Affichage carte
if (mapViewEnabled) {
displayBackGroundMap(g);
}
g.setColor(new Color(0x10, 0x50, 0xA0));
for (int i = 0; i < size; i++) {
new StationButton(this, stations[i]);
}
// Dessine les lignes avec des couleurs différentes les unes des autres
for (int i = 0; i < lsize; i++) {
g.setColor(new Color((125 / lsize) * i, (125 / lsize) * i,
(255 / lsize) * i));
int ssize = lines[i].getStations().size();
//Dessine des lignes en fonction de la taille de la fenêtre
Graphics2D g2 = (Graphics2D) g;
int ltaille = Math.min(this.getWidth(), this.getHeight())/200;
g2.setStroke(new BasicStroke(ltaille));
for (int j = 0; j < ssize - 1; j++) {
g2.drawLine((int) ((int) (ltaille/2 + xMid - (longMid - lines[i]
.getStations().get(j).getLongitude())
* scalingX)),
(int) (yMid + (ltaille/2 + scalingY * (latMid - lines[i]
.getStations().get(j).getLatitude()))),
(int) ((int) (ltaille/2 + xMid - (longMid - lines[i].getStations()
.get(j + 1).getLongitude())
* scalingX)),
(int) (ltaille/2 + yMid + (scalingY * (latMid - lines[i]
.getStations().get(j + 1).getLatitude()))));
}
}
}
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
}
/**
* Permet d'afficher une carte en fond, non fonctionnel actuellement
*/
public void displayBackGroundMap(Graphics g) {
String url = "http://www.mapquestapi.com/staticmap/v4/getmap?key=Fmjtd|luua2068nh,22=o5-967xlr";
url += "&bestfit="
+ (yDeb - (y / scalingY - distanceY) / 2 + yDec)
+ ","
+ (xDeb - (x / scalingX - distanceX) / 2 + xDec)
+ ","
+ ((yDeb - (y / scalingY - distanceY) / 2 + yDec) + y
/ scalingY)
+ ","
+ ((xDeb - (x / scalingX - distanceX) / 2 + xDec) + x
/ scalingX);
url += "&size=" + this.getWidth() + "," + this.getHeight();
url += "&type="+mapType+"&imagetype=jpeg&traffic=FLOW";
if (!url.equals(this.urlBackGroundImage)) {
URL imgURL;
try {
imgURL = new URL(url);
System.out.println("image url : " + imgURL);
if (imgURL != null) {
this.urlBackGroundImage = url;
this.backGroundImage = new ImageIcon(imgURL);
}
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
//On affiche l'image
g.drawImage(this.backGroundImage.getImage(), 0, 0, null);
}
@Override
public void actionPerformed(ActionEvent e) {
}
}