/*******************************************************************************
* This file is part of logisim-evolution.
*
* logisim-evolution is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* logisim-evolution is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with logisim-evolution. If not, see <http://www.gnu.org/licenses/>.
*
* Original code by Carl Burch (http://www.cburch.com), 2011.
* Subsequent modifications by :
* + Haute École Spécialisée Bernoise
* http://www.bfh.ch
* + Haute École du paysage, d'ingénierie et d'architecture de Genève
* http://hepia.hesge.ch/
* + Haute École d'Ingénierie et de Gestion du Canton de Vaud
* http://www.heig-vd.ch/
* The project is currently maintained by :
* + REDS Institute - HEIG-VD
* Yverdon-les-Bains, Switzerland
* http://reds.heig-vd.ch
*******************************************************************************/
package com.bfh.logisim.fpgaboardeditor;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Iterator;
import java.util.LinkedList;
import javax.imageio.ImageIO;
import javax.swing.JFileChooser;
import javax.swing.JPanel;
import javax.swing.filechooser.FileFilter;
@SuppressWarnings("serial")
public class BoardPanel extends JPanel implements MouseListener,
MouseMotionListener {
private static class PNGFileFilter extends FileFilter {
@Override
public boolean accept(File f) {
return f.isDirectory() || f.getName().endsWith(PNG_EXTENSION);
}
@Override
public String getDescription() {
return Strings.get("PNG File Filter"); // TODO: language adaptation
}
}
/**
*
*/
private int image_width = 740;
private int image_height = 400;
private BufferedImage image;
private int xs, ys, w, h;
private Boolean EditMode;
public static final String PNG_EXTENSION = ".png";
public static final FileFilter PNG_FILTER = new PNGFileFilter();
private int scale = 1;
private BoardDialog edit_parent;
public BoardPanel(BoardDialog parent) {
xs = ys = w = h = 0;
image = null;
EditMode = true;
Dimension thedim = new Dimension();
thedim.width = getWidth();
thedim.height = getHeight();
edit_parent = parent;
super.setPreferredSize(thedim);
this.addMouseListener(this);
this.addMouseMotionListener(this);
}
public BoardPanel(URL filename) {
xs = ys = w = h = 0;
try {
image = ImageIO.read(filename);
} catch (IOException ex) {
image = null;
}
EditMode = false;
Dimension thedim = new Dimension();
thedim.width = getWidth();
thedim.height = getHeight();
super.setPreferredSize(thedim);
this.addMouseListener(this);
this.addMouseMotionListener(this);
}
public void setScale(int scale) {
this.scale = scale;
Dimension thedim = new Dimension();
thedim.width = getWidth();
thedim.height = getHeight();
super.setPreferredSize(thedim);
}
public void clear() {
image = null;
}
public int getImageWidth() {
return (image.getWidth()<3*image_width) ? image.getWidth() : 3*image_width;
}
public int getImageHeight() {
return (image.getHeight()<3*image_height) ? image.getHeight() : 3*image_height;
}
public int getHeight() {
return image_height*scale;
}
public Image getScaledImage(int width, int height) {
return image.getScaledInstance(width, height, 4);
}
public int getWidth() {
return image_width*scale;
}
public Boolean ImageLoaded() {
return image != null;
}
public void mouseClicked(MouseEvent e) {
if (EditMode && !this.ImageLoaded()) {
JFileChooser fc = new JFileChooser();
fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
fc.setDialogTitle("Choose FPGA board picture to use");
fc.setFileFilter(PNG_FILTER);
fc.setAcceptAllFileFilterUsed(false);
int retval = fc.showOpenDialog(null);
if (retval == JFileChooser.APPROVE_OPTION) {
File file = fc.getSelectedFile();
try {
image = ImageIO.read(file);
} catch (IOException ex) {
image = null;
}
this.repaint();
edit_parent.SetBoardName(file.getName());
}
}
}
public void mouseDragged(MouseEvent e) {
if (EditMode && this.ImageLoaded()) {
this.set_drag(e.getX()/scale, e.getY()/scale);
this.repaint();
}
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mouseMoved(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
if (e.getClickCount() > 1) {
this.set_start(0, 0);
edit_parent.EditDialog(e.getX()/scale, e.getY()/scale);
} else
this.set_start(e.getX()/scale, e.getY()/scale);
}
public void mouseReleased(MouseEvent e) {
if (EditMode && this.ImageLoaded() && (h != 0) && (w != 0)) {
BoardRectangle rect = new BoardRectangle(xs, ys, w, h);
edit_parent.SelectDialog(rect);
this.set_start(0, 0);
this.repaint();
}
}
public void paint(Graphics g) {
super.paint(g);
if (image != null) {
g.drawImage(getScaledImage(getWidth(), getHeight()), 0, 0, null);
g.setColor(Color.red);
if ((w != 0) || (h != 0)) {
int xr, yr, wr, hr;
xr = (w < 0) ? xs + w : xs;
yr = (h < 0) ? ys + h : ys;
wr = (w < 0) ? -w : w;
hr = (h < 0) ? -h : h;
g.drawRect(xr*scale, yr*scale, wr*scale, hr*scale);
}
if (EditMode && (edit_parent.defined_components != null)) {
LinkedList<BoardRectangle> comps = edit_parent.defined_components;
Iterator<BoardRectangle> iter = comps.iterator();
g.setColor(Color.red);
while (iter.hasNext()) {
BoardRectangle thisone = iter.next();
g.fillRect(thisone.getXpos()*scale, thisone.getYpos()*scale,
thisone.getWidth()*scale, thisone.getHeight()*scale);
}
}
} else {
g.setColor(Color.gray);
g.fillRect(0, 0, getWidth(), getHeight());
if (EditMode) {
String message;
int xpos;
Font curfont = new Font(g.getFont().getFontName(), Font.BOLD,
20*scale);
g.setColor(Color.black);
g.setFont(curfont);
FontMetrics fm = g.getFontMetrics();
message = "Click here to add a board picture.";
xpos = (this.getWidth() - fm.stringWidth(message)) / 2;
g.drawString(message, xpos, 100);
message = "The board picture should have at least a resolution of";
xpos = (this.getWidth() - fm.stringWidth(message)) / 2;
g.drawString(message, xpos, 200);
message = image_width + "x" + image_height
+ " pixels (width x height)";
xpos = (this.getWidth() - fm.stringWidth(message)) / 2;
g.drawString(message, xpos, (200 + (int) (1.5 * fm.getAscent())) );
message = "for best graphical display.";
xpos = (this.getWidth() - fm.stringWidth(message)) / 2;
g.drawString(message, xpos, (200 + (int) (3 * fm.getAscent())) );
message = "The board picture formate must be PNG";
xpos = (this.getWidth() - fm.stringWidth(message)) / 2;
g.drawString(message, xpos, (200 + (int) (4.5 * fm.getAscent())) );
if (scale > 1) {
message = "Current resolution: "+getWidth()+"x"+getHeight();
xpos = (this.getWidth() - fm.stringWidth(message)) / 2;
g.drawString(message, xpos, (200 + (int) (6 * fm.getAscent())) );
}
}
}
}
public void set_drag(int x, int y) {
if (EditMode && this.ImageLoaded()) {
w = x - xs;
h = y - ys;
}
}
public void set_start(int x, int y) {
if (EditMode && this.ImageLoaded()) {
xs = x;
ys = y;
w = 0;
h = 0;
}
}
public void SetImage(BufferedImage pic) {
image = pic;
this.repaint();
}
}