mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
Updated led simulation (little bit faster and behind a worker to keep gui responsive)
Former-commit-id: 45d6a3d0243f5fb3a0bbcb03f2276e13b683c182
This commit is contained in:
parent
e1e88ba2cf
commit
2879f44f08
@ -1 +1 @@
|
||||
85ee9ddb3d9a3dd3ba63e1d1d8b21e3616cb79ae
|
||||
fb506ad21f8aabad449e751a8b48337d61be16eb
|
@ -1,7 +1,6 @@
|
||||
package org.hyperion.hypercon.gui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -64,7 +63,7 @@ public class ConfigPanel extends JPanel {
|
||||
/** The panel for containing the example 'Hyperion TV' */
|
||||
private JPanel mTvPanel;
|
||||
/** The simulated 'Hyperion TV' */
|
||||
private JHyperionTv mHyperionTv;
|
||||
private LedSimulationComponent mHyperionTv;
|
||||
|
||||
private JTabbedPane mSpecificationTabs = null;
|
||||
/** The left (WEST) side panel containing the diferent configuration panels */
|
||||
@ -148,7 +147,7 @@ public class ConfigPanel extends JPanel {
|
||||
mTvPanel = new JPanel();
|
||||
mTvPanel.setLayout(new BorderLayout());
|
||||
|
||||
mHyperionTv = new JHyperionTv();
|
||||
mHyperionTv = new LedSimulationComponent(ledString.leds);
|
||||
mTvPanel.add(mHyperionTv, BorderLayout.CENTER);
|
||||
}
|
||||
return mTvPanel;
|
||||
|
@ -0,0 +1,27 @@
|
||||
package org.hyperion.hypercon.gui;
|
||||
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Image;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
|
||||
public class ImageComponent extends JComponent {
|
||||
|
||||
private Image mImage;
|
||||
|
||||
public ImageComponent() {
|
||||
super();
|
||||
}
|
||||
|
||||
public void setImage(Image pImage) {
|
||||
mImage = pImage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
if (mImage == null) {
|
||||
return;
|
||||
}
|
||||
g.drawImage(mImage, 0, 0, getWidth(), getHeight(), null);
|
||||
}
|
||||
}
|
@ -1,346 +0,0 @@
|
||||
package org.hyperion.hypercon.gui;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseMotionListener;
|
||||
import java.awt.font.LineMetrics;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.util.Vector;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.SwingWorker;
|
||||
|
||||
import org.hyperion.hypercon.spec.Led;
|
||||
|
||||
public class JHyperionTv extends Component {
|
||||
|
||||
private JPopupMenu mPopupMenu;
|
||||
private final Action mLoadAction = new AbstractAction("Load image...") {
|
||||
JFileChooser mImageChooser;
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (mImageChooser == null) {
|
||||
mImageChooser = new JFileChooser();
|
||||
}
|
||||
|
||||
if (mImageChooser.showOpenDialog(JHyperionTv.this) != JFileChooser.APPROVE_OPTION) {
|
||||
return;
|
||||
}
|
||||
File file = mImageChooser.getSelectedFile();
|
||||
|
||||
try {
|
||||
ImageIcon imageIcon = new ImageIcon(file.getAbsolutePath());
|
||||
Image image = imageIcon.getImage();
|
||||
mRawImage = image;
|
||||
repaint();
|
||||
} catch (Exception ex) {
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private class SelectImageAction extends AbstractAction {
|
||||
private final String mImageName;
|
||||
SelectImageAction(String pImageName) {
|
||||
super(pImageName);
|
||||
mImageName = pImageName;
|
||||
|
||||
ImageIcon image = loadImage();
|
||||
if (image != null) {
|
||||
Image scaledImage = image.getImage().getScaledInstance(32, 18, Image.SCALE_SMOOTH);
|
||||
ImageIcon scaledIcon = new ImageIcon(scaledImage, mImageName);
|
||||
putValue(SMALL_ICON, scaledIcon);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
ImageIcon imageIcon = loadImage();
|
||||
if (imageIcon != null) {
|
||||
mRawImage = imageIcon.getImage();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
ImageIcon loadImage() {
|
||||
URL imageUrl = JHyperionTv.class.getResource(mImageName + ".png");
|
||||
if (imageUrl == null) {
|
||||
System.out.println("Failed to load image: " + mImageName);
|
||||
return null;
|
||||
}
|
||||
return new ImageIcon(imageUrl);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized JPopupMenu getPopupMenu() {
|
||||
if (mPopupMenu == null) {
|
||||
mPopupMenu = new JPopupMenu();
|
||||
mPopupMenu.add(mLoadAction);
|
||||
|
||||
JMenu selectMenu = new JMenu("Select Image");
|
||||
selectMenu.add(new SelectImageAction("TestImage_01"));
|
||||
selectMenu.add(new SelectImageAction("TestImage_02"));
|
||||
selectMenu.add(new SelectImageAction("TestImage_03"));
|
||||
selectMenu.add(new SelectImageAction("TestImage_04"));
|
||||
selectMenu.add(new SelectImageAction("TestImage_05"));
|
||||
selectMenu.add(new SelectImageAction("TestImageBBB_01"));
|
||||
selectMenu.add(new SelectImageAction("TestImageBBB_02"));
|
||||
selectMenu.add(new SelectImageAction("TestImageBBB_03"));
|
||||
mPopupMenu.add(selectMenu);
|
||||
}
|
||||
return mPopupMenu;
|
||||
}
|
||||
|
||||
private Image mRawImage = new ImageIcon(JHyperionTv.class.getResource("TestImage_01.png")).getImage();
|
||||
|
||||
int lightBorder = 100;
|
||||
int tvBorder = 12;
|
||||
|
||||
private class LedWrapper {
|
||||
public final Led led;
|
||||
|
||||
public int lastX = 0;
|
||||
public int lastY = 0;
|
||||
|
||||
public LedWrapper(Led pLed) {
|
||||
led = pLed;
|
||||
}
|
||||
}
|
||||
private final Vector<LedWrapper> mLeds2 = new Vector<>();
|
||||
|
||||
public void setLeds(Vector<Led> pLeds) {
|
||||
mLeds2.clear();
|
||||
|
||||
for (Led led : pLeds) {
|
||||
mLeds2.add(new LedWrapper(led));
|
||||
}
|
||||
}
|
||||
|
||||
LedWrapper mSelLed = null;
|
||||
|
||||
public JHyperionTv() {
|
||||
|
||||
// Pre-cache the popup menu
|
||||
new SwingWorker<Object, Object>() {
|
||||
@Override
|
||||
protected Object doInBackground() throws Exception {
|
||||
return getPopupMenu();
|
||||
}
|
||||
}.execute();
|
||||
|
||||
addMouseMotionListener(new MouseMotionListener() {
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
mSelLed = null;
|
||||
|
||||
double x = (double)(e.getX() - lightBorder - tvBorder) / (getWidth() - lightBorder*2-tvBorder*2);
|
||||
double y = (double)(e.getY() - lightBorder - tvBorder) / (getHeight() - lightBorder*2-tvBorder*2);
|
||||
|
||||
for (LedWrapper led : mLeds2) {
|
||||
if (led.led.mImageRectangle.contains(x, y) || (Math.abs(led.led.mLocation.getX() - x) < 0.01 && Math.abs(led.led.mLocation.getY() - y) < 0.01)) {
|
||||
mSelLed = led;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
repaint();
|
||||
}
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
|
||||
}
|
||||
});
|
||||
addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
showPopup(e);
|
||||
}
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
showPopup(e);
|
||||
}
|
||||
private void showPopup(MouseEvent e) {
|
||||
if (!e.isPopupTrigger()) {
|
||||
return;
|
||||
}
|
||||
getPopupMenu().show(JHyperionTv.this, e.getX(), e.getY());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
super.paint(g);
|
||||
if (getWidth() <= 2*lightBorder+2*tvBorder+10 || getHeight() <= 2*lightBorder+2*tvBorder+10) {
|
||||
return;
|
||||
}
|
||||
|
||||
Graphics2D g2d = (Graphics2D) g.create();
|
||||
g2d.setColor(Color.BLACK);
|
||||
g2d.fillRect(0, 0, getWidth(), getHeight());
|
||||
|
||||
int screenWidth = getWidth() - 2*lightBorder;
|
||||
int screenHeight = getHeight() - 2*lightBorder;
|
||||
int imageWidth = screenWidth - 2*tvBorder;
|
||||
int imageHeight = screenHeight- 2*tvBorder;
|
||||
|
||||
g2d.translate((getWidth() - imageWidth)/2, (getHeight() - imageHeight)/2);
|
||||
|
||||
BufferedImage image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB);
|
||||
image.getGraphics().drawImage(mRawImage, 0, 0, image.getWidth(), image.getHeight(), null);
|
||||
|
||||
if (mLeds2 != null) {
|
||||
paintAllLeds(g2d, screenWidth, screenHeight, image);
|
||||
}
|
||||
|
||||
g2d.setColor(Color.DARK_GRAY.darker());
|
||||
g2d.fillRect(-tvBorder, -tvBorder, screenWidth, screenHeight);
|
||||
g2d.drawImage(image, 0, 0, imageWidth, imageHeight, this);
|
||||
|
||||
paintLedNumbers(g2d);
|
||||
|
||||
for (LedWrapper led : mLeds2) {
|
||||
g2d.setColor(Color.GRAY);
|
||||
|
||||
int xmin = (int)(led.led.mImageRectangle.getMinX() * (imageWidth-1));
|
||||
int xmax = (int)(led.led.mImageRectangle.getMaxX()* (imageWidth-1));
|
||||
|
||||
int ymin = (int)(led.led.mImageRectangle.getMinY() * (imageHeight-1));
|
||||
int ymax = (int)(led.led.mImageRectangle.getMaxY() * (imageHeight-1));
|
||||
|
||||
g2d.drawRect(xmin, ymin, (xmax-xmin), (ymax-ymin));
|
||||
}
|
||||
if (mSelLed != null) {
|
||||
g2d.setStroke(new BasicStroke(3.0f));
|
||||
g2d.setColor(Color.WHITE);
|
||||
|
||||
int xmin = (int)(mSelLed.led.mImageRectangle.getMinX() * (imageWidth-1));
|
||||
int xmax = (int)(mSelLed.led.mImageRectangle.getMaxX()* (imageWidth-1));
|
||||
|
||||
int ymin = (int)(mSelLed.led.mImageRectangle.getMinY() * (imageHeight-1));
|
||||
int ymax = (int)(mSelLed.led.mImageRectangle.getMaxY() * (imageHeight-1));
|
||||
|
||||
g2d.drawRect(xmin, ymin, (xmax-xmin), (ymax-ymin));
|
||||
}
|
||||
|
||||
Graphics2D gCopy = (Graphics2D)g.create();
|
||||
gCopy.setXORMode(Color.WHITE);
|
||||
gCopy.setFont(gCopy.getFont().deriveFont(20.0f));
|
||||
String ledCntStr = "Led count: " + mLeds2.size();
|
||||
gCopy.drawString(ledCntStr, getWidth()-150.0f, getHeight()-10.0f);
|
||||
}
|
||||
|
||||
class LedPaint {
|
||||
int xmin;
|
||||
int xmax;
|
||||
int ymin;
|
||||
int ymax;
|
||||
|
||||
int color;
|
||||
int seqNr;
|
||||
|
||||
int screenX;
|
||||
int screenY;
|
||||
double angle_rad;
|
||||
}
|
||||
|
||||
private void paintAllLeds(Graphics2D g2d, int screenWidth, int screenHeight, BufferedImage image) {
|
||||
Dimension screenDimension = new Dimension(getWidth()-2*lightBorder-2*tvBorder, getHeight()-2*lightBorder-2*tvBorder);
|
||||
|
||||
int imageWidth = image.getWidth();
|
||||
int imageHeight = image.getHeight();
|
||||
|
||||
Vector<LedPaint> ledPaints = new Vector<>();
|
||||
|
||||
for (LedWrapper led : mLeds2) {
|
||||
LedPaint ledPaint = new LedPaint();
|
||||
ledPaint.xmin = (int)(led.led.mImageRectangle.getMinX() * (imageWidth-1));
|
||||
ledPaint.xmax = (int)(led.led.mImageRectangle.getMaxX()* (imageWidth-1));
|
||||
ledPaint.ymin = (int)(led.led.mImageRectangle.getMinY() * (imageHeight-1));
|
||||
ledPaint.ymax = (int)(led.led.mImageRectangle.getMaxY() * (imageHeight-1));
|
||||
|
||||
int red = 0;
|
||||
int green = 0;
|
||||
int blue = 0;
|
||||
int count = 0;
|
||||
|
||||
for (int y = ledPaint.ymin; y <= ledPaint.ymax; ++y) {
|
||||
for (int x = ledPaint.xmin; x <= ledPaint.xmax; ++x) {
|
||||
int color = image.getRGB(x, y);
|
||||
red += (color >> 16) & 0xFF;
|
||||
green += (color >> 8) & 0xFF;
|
||||
blue += color & 0xFF;
|
||||
++count;
|
||||
}
|
||||
}
|
||||
ledPaint.color = count > 0 ? new Color(red / count, green/count, blue/count).getRGB() : 0;
|
||||
|
||||
ledPaints.add(ledPaint);
|
||||
|
||||
led.lastX = (int) (screenDimension.width * led.led.mLocation.getX());
|
||||
led.lastY = (int) (screenDimension.height * led.led.mLocation.getY());
|
||||
|
||||
ledPaint.screenX = led.lastX;
|
||||
ledPaint.screenY = led.lastY;
|
||||
ledPaint.angle_rad = 0.5*Math.PI - led.led.mSide.getAngle_rad();
|
||||
|
||||
ledPaint.seqNr = led.led.mLedSeqNr;
|
||||
}
|
||||
|
||||
for (int i=2; i<=180; i+=4) {
|
||||
int arcSize = 24 + (int)((i/12.0)*(i/12.0));
|
||||
|
||||
for(LedPaint led : ledPaints) {
|
||||
int argb = 0x05000000 | (0x00ffffff & led.color);
|
||||
g2d.setColor(new Color(argb , true));
|
||||
|
||||
g2d.translate(led.screenX, led.screenY);
|
||||
g2d.rotate(led.angle_rad);
|
||||
g2d.fillArc(-arcSize, -arcSize, 2*arcSize, 2*arcSize, 90-(i/2), i);
|
||||
g2d.rotate(-led.angle_rad);
|
||||
g2d.translate(-led.screenX, -led.screenY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void paintLedNumbers(Graphics2D pG2d) {
|
||||
pG2d.setColor(Color.GRAY);
|
||||
|
||||
FontMetrics fontMetrics = pG2d.getFontMetrics();
|
||||
for (LedWrapper led : mLeds2) {
|
||||
String seqNrStr = "" + led.led.mLedSeqNr;
|
||||
Rectangle2D rect = fontMetrics.getStringBounds(seqNrStr, pG2d);
|
||||
|
||||
pG2d.drawString("" + led.led.mLedSeqNr, (int)(led.lastX-rect.getWidth()/2), (int)(led.lastY+rect.getHeight()/2-2));
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] pArgs) {
|
||||
JFrame frame = new JFrame();
|
||||
frame.setSize(640, 480);
|
||||
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
|
||||
|
||||
frame.getContentPane().setLayout(new BorderLayout());
|
||||
frame.getContentPane().add(new JHyperionTv());
|
||||
|
||||
frame.setVisible(true);
|
||||
}
|
||||
}
|
@ -0,0 +1,313 @@
|
||||
package org.hyperion.hypercon.gui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Image;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.util.Vector;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.JProgressBar;
|
||||
|
||||
import org.hyperion.hypercon.LedFrameFactory;
|
||||
import org.hyperion.hypercon.spec.ImageProcessConfig;
|
||||
import org.hyperion.hypercon.spec.Led;
|
||||
import org.hyperion.hypercon.spec.LedFrameConstruction;
|
||||
|
||||
|
||||
public class LedSimulationComponent extends JPanel {
|
||||
|
||||
private double mBorderFraction = 0.2;
|
||||
|
||||
private BufferedImage mTvImage = new BufferedImage(640, 480, BufferedImage.TYPE_INT_ARGB);
|
||||
|
||||
private void setImage(Image pImage) {
|
||||
mTvImage.createGraphics().drawImage(pImage, 0, 0, mTvImage.getWidth(), mTvImage.getHeight(), null);
|
||||
}
|
||||
{
|
||||
Image image = new ImageIcon(LedSimulationComponent.class.getResource("TestImage_01.png")).getImage();
|
||||
mTvImage.createGraphics().drawImage(image, 0, 0, mTvImage.getWidth(), mTvImage.getHeight(), null);
|
||||
}
|
||||
|
||||
private JPanel mTopPanel;
|
||||
private ImageComponent mTopLeftImage;
|
||||
private ImageComponent mTopImage;
|
||||
private ImageComponent mTopRightImage;
|
||||
|
||||
private ImageComponent mLeftImage;
|
||||
private ImageComponent mRightImage;
|
||||
|
||||
private JPanel mBottomPanel;
|
||||
private ImageComponent mBottomLeftImage;
|
||||
private ImageComponent mBottomImage;
|
||||
private ImageComponent mBottomRightImage;
|
||||
private JProgressBar mProgressBar;
|
||||
|
||||
LedTvComponent mTvComponent;
|
||||
|
||||
public LedSimulationComponent(Vector<Led> pLeds) {
|
||||
super();
|
||||
|
||||
initialise(pLeds);
|
||||
|
||||
setLeds(pLeds);
|
||||
}
|
||||
|
||||
void initialise(Vector<Led> pLeds) {
|
||||
setBackground(Color.BLACK);
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
add(getTopPanel(), BorderLayout.NORTH);
|
||||
|
||||
mLeftImage = new ImageComponent();
|
||||
mLeftImage.setPreferredSize(new Dimension(100,100));
|
||||
add(mLeftImage, BorderLayout.WEST);
|
||||
mRightImage = new ImageComponent();
|
||||
mRightImage.setPreferredSize(new Dimension(100,100));
|
||||
add(mRightImage, BorderLayout.EAST);
|
||||
|
||||
add(getBottomPanel(), BorderLayout.SOUTH);
|
||||
|
||||
mTvComponent = new LedTvComponent(pLeds);
|
||||
mTvComponent.setImage(mTvImage);
|
||||
add(mTvComponent, BorderLayout.CENTER);
|
||||
|
||||
mTvComponent.addMouseListener(mPopupListener);
|
||||
}
|
||||
|
||||
private JPanel getTopPanel() {
|
||||
mTopPanel = new JPanel();
|
||||
mTopPanel.setPreferredSize(new Dimension(100,100));
|
||||
mTopPanel.setBackground(Color.BLACK);
|
||||
mTopPanel.setLayout(new BorderLayout());
|
||||
|
||||
mTopLeftImage = new ImageComponent();
|
||||
mTopLeftImage.setPreferredSize(new Dimension(100,100));
|
||||
mTopPanel.add(mTopLeftImage, BorderLayout.WEST);
|
||||
mTopImage = new ImageComponent();
|
||||
mTopPanel.add(mTopImage, BorderLayout.CENTER);
|
||||
mTopRightImage = new ImageComponent();
|
||||
mTopRightImage.setPreferredSize(new Dimension(100,100));
|
||||
mTopPanel.add(mTopRightImage, BorderLayout.EAST);
|
||||
|
||||
return mTopPanel;
|
||||
}
|
||||
|
||||
private JPanel getBottomPanel() {
|
||||
mBottomPanel = new JPanel();
|
||||
mBottomPanel.setPreferredSize(new Dimension(100,100));
|
||||
mBottomPanel.setBackground(Color.BLACK);
|
||||
mBottomPanel.setLayout(new BorderLayout());
|
||||
|
||||
mBottomLeftImage = new ImageComponent();
|
||||
mBottomLeftImage.setPreferredSize(new Dimension(100,100));
|
||||
mBottomPanel.add(mBottomLeftImage, BorderLayout.WEST);
|
||||
mBottomImage = new ImageComponent();
|
||||
mBottomPanel.add(mBottomImage, BorderLayout.CENTER);
|
||||
mBottomRightImage = new ImageComponent();
|
||||
mBottomRightImage.setPreferredSize(new Dimension(100,100));
|
||||
mBottomPanel.add(mBottomRightImage, BorderLayout.EAST);
|
||||
|
||||
mProgressBar = new JProgressBar(0, 100);
|
||||
mBottomPanel.add(mProgressBar, BorderLayout.SOUTH);
|
||||
|
||||
return mBottomPanel;
|
||||
}
|
||||
|
||||
|
||||
LedSimulationWorker mWorker = null;
|
||||
|
||||
public void setLeds(Vector<Led> pLeds) {
|
||||
mTvComponent.setLeds(pLeds);
|
||||
|
||||
synchronized (LedSimulationComponent.this) {
|
||||
if (mWorker != null) {
|
||||
mWorker.cancel(true);
|
||||
}
|
||||
mWorker = null;
|
||||
}
|
||||
mWorker = new LedSimulationWorker(mTvImage, pLeds);
|
||||
mProgressBar.setValue(0);
|
||||
mWorker.addPropertyChangeListener(new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
BufferedImage backgroundImage = null;
|
||||
|
||||
synchronized(LedSimulationComponent.this) {
|
||||
if (mWorker == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (evt.getPropertyName() == "progress") {
|
||||
mProgressBar.setValue(mWorker.getProgress());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mWorker.isDone()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
backgroundImage = mWorker.get();
|
||||
mWorker = null;
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
if (backgroundImage == null) {
|
||||
return;
|
||||
}
|
||||
int width = backgroundImage.getWidth();
|
||||
int height = backgroundImage.getHeight();
|
||||
int borderWidth = (int) (backgroundImage.getWidth() * mBorderFraction);
|
||||
int borderHeight = (int) (backgroundImage.getHeight() * mBorderFraction);
|
||||
|
||||
mTopLeftImage.setImage(backgroundImage.getSubimage(0, 0, borderWidth, borderHeight));
|
||||
mTopImage.setImage(backgroundImage.getSubimage(borderWidth, 0, width-2*borderWidth, borderHeight));
|
||||
mTopRightImage.setImage(backgroundImage.getSubimage(width-borderWidth, 0, borderWidth, borderHeight));
|
||||
|
||||
mLeftImage.setImage(backgroundImage.getSubimage(0, borderHeight, borderWidth, height-2*borderHeight));
|
||||
mRightImage.setImage(backgroundImage.getSubimage(width-borderWidth, borderHeight, borderWidth, height-2*borderHeight));
|
||||
|
||||
mBottomLeftImage.setImage(backgroundImage.getSubimage(0, height-borderHeight, borderWidth, borderHeight));
|
||||
mBottomImage.setImage(backgroundImage.getSubimage(borderWidth, height-borderHeight, width-2*borderWidth, borderHeight));
|
||||
mBottomRightImage.setImage(backgroundImage.getSubimage(width-borderWidth, height-borderHeight, borderWidth, borderHeight));
|
||||
|
||||
mProgressBar.setValue(100);
|
||||
mWorker = null;
|
||||
|
||||
LedSimulationComponent.this.repaint();
|
||||
}
|
||||
});
|
||||
mWorker.execute();
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] pArgs) {
|
||||
JFrame frame = new JFrame();
|
||||
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
|
||||
frame.setSize(800, 600);
|
||||
|
||||
Vector<Led> leds = LedFrameFactory.construct(new LedFrameConstruction(), new ImageProcessConfig());
|
||||
|
||||
LedSimulationComponent ledSimComp = new LedSimulationComponent(leds);
|
||||
|
||||
frame.getContentPane().setLayout(new BorderLayout());
|
||||
frame.getContentPane().add(ledSimComp);
|
||||
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
private final MouseListener mPopupListener = new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
showPopup(e);
|
||||
}
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
showPopup(e);
|
||||
}
|
||||
private void showPopup(MouseEvent e) {
|
||||
if (!e.isPopupTrigger()) {
|
||||
return;
|
||||
}
|
||||
getPopupMenu().show(mTvComponent, e.getX(), e.getY());
|
||||
}
|
||||
};
|
||||
|
||||
private JPopupMenu mPopupMenu;
|
||||
private final Action mLoadAction = new AbstractAction("Load image...") {
|
||||
JFileChooser mImageChooser;
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (mImageChooser == null) {
|
||||
mImageChooser = new JFileChooser();
|
||||
}
|
||||
|
||||
if (mImageChooser.showOpenDialog(mTvComponent) != JFileChooser.APPROVE_OPTION) {
|
||||
return;
|
||||
}
|
||||
File file = mImageChooser.getSelectedFile();
|
||||
|
||||
try {
|
||||
ImageIcon imageIcon = new ImageIcon(file.getAbsolutePath());
|
||||
Image image = imageIcon.getImage();
|
||||
|
||||
mTvComponent.setImage(image);
|
||||
// setIma
|
||||
} catch (Exception ex) {
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private synchronized JPopupMenu getPopupMenu() {
|
||||
if (mPopupMenu == null) {
|
||||
mPopupMenu = new JPopupMenu();
|
||||
mPopupMenu.add(mLoadAction);
|
||||
|
||||
JMenu selectMenu = new JMenu("Select Image");
|
||||
selectMenu.add(new SelectImageAction("TestImage_01"));
|
||||
selectMenu.add(new SelectImageAction("TestImage_02"));
|
||||
selectMenu.add(new SelectImageAction("TestImage_03"));
|
||||
selectMenu.add(new SelectImageAction("TestImage_04"));
|
||||
selectMenu.add(new SelectImageAction("TestImage_05"));
|
||||
selectMenu.add(new SelectImageAction("TestImageBBB_01"));
|
||||
selectMenu.add(new SelectImageAction("TestImageBBB_02"));
|
||||
selectMenu.add(new SelectImageAction("TestImageBBB_03"));
|
||||
mPopupMenu.add(selectMenu);
|
||||
}
|
||||
return mPopupMenu;
|
||||
}
|
||||
|
||||
private class SelectImageAction extends AbstractAction {
|
||||
private final String mImageName;
|
||||
SelectImageAction(String pImageName) {
|
||||
super(pImageName);
|
||||
mImageName = pImageName;
|
||||
|
||||
ImageIcon image = loadImage();
|
||||
if (image != null) {
|
||||
Image scaledImage = image.getImage().getScaledInstance(32, 18, Image.SCALE_SMOOTH);
|
||||
ImageIcon scaledIcon = new ImageIcon(scaledImage, mImageName);
|
||||
putValue(SMALL_ICON, scaledIcon);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
ImageIcon imageIcon = loadImage();
|
||||
if (imageIcon != null) {
|
||||
Image image = imageIcon.getImage();
|
||||
|
||||
setImage(image);
|
||||
mTvComponent.setImage(image);
|
||||
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
ImageIcon loadImage() {
|
||||
URL imageUrl = LedSimulationComponent.class.getResource(mImageName + ".png");
|
||||
if (imageUrl == null) {
|
||||
System.out.println("Failed to load image: " + mImageName);
|
||||
return null;
|
||||
}
|
||||
return new ImageIcon(imageUrl);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,135 @@
|
||||
package org.hyperion.hypercon.gui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
import javax.swing.SwingWorker;
|
||||
|
||||
import org.hyperion.hypercon.spec.Led;
|
||||
|
||||
public class LedSimulationWorker extends SwingWorker<BufferedImage, Object> {
|
||||
|
||||
private final double mBorderFraction = 0.2;
|
||||
|
||||
private final BufferedImage mTvImage;
|
||||
|
||||
private final Vector<Led> mLeds;
|
||||
|
||||
public LedSimulationWorker(BufferedImage pTvImage, Vector<Led> pLeds) {
|
||||
super();
|
||||
|
||||
mTvImage = pTvImage;
|
||||
mLeds = pLeds;
|
||||
}
|
||||
|
||||
class LedPaint {
|
||||
int color;
|
||||
|
||||
Point point;
|
||||
double angle_rad;
|
||||
}
|
||||
|
||||
private final List<LedPaint> mLedPaints = new Vector<>();
|
||||
|
||||
|
||||
@Override
|
||||
protected BufferedImage doInBackground() throws Exception {
|
||||
Dimension imageDim = new Dimension(1280, 720);
|
||||
BufferedImage backgroundImage = new BufferedImage(imageDim.width, imageDim.height, BufferedImage.TYPE_INT_ARGB);
|
||||
|
||||
mLedPaints.clear();
|
||||
|
||||
setProgress(5);
|
||||
|
||||
int imageWidth = mTvImage.getWidth();
|
||||
int imageHeight = mTvImage.getHeight();
|
||||
for (Led led : mLeds) {
|
||||
LedPaint ledPaint = new LedPaint();
|
||||
|
||||
// Determine the location and orientation of the led on the image
|
||||
ledPaint.point = tv2image(imageDim, led.mLocation);
|
||||
ledPaint.angle_rad = 0.5*Math.PI - led.mSide.getAngle_rad();
|
||||
|
||||
// Determine the color of the led
|
||||
int xMin = (int)(led.mImageRectangle.getMinX() * (imageWidth-1));
|
||||
int xMax = (int)(led.mImageRectangle.getMaxX() * (imageWidth-1));
|
||||
int yMin = (int)(led.mImageRectangle.getMinY() * (imageHeight-1));
|
||||
int yMax = (int)(led.mImageRectangle.getMaxY() * (imageHeight-1));
|
||||
ledPaint.color = determineColor(xMin, xMax, yMin, yMax);
|
||||
|
||||
mLedPaints.add(ledPaint);
|
||||
}
|
||||
|
||||
setProgress(10);
|
||||
|
||||
Graphics2D g2d = backgroundImage.createGraphics();
|
||||
// Clear the image with a black rectangle
|
||||
g2d.setColor(Color.BLACK);
|
||||
g2d.drawRect(0, 0, backgroundImage.getWidth(), backgroundImage.getHeight());
|
||||
paintAllLeds(g2d);
|
||||
|
||||
return backgroundImage;
|
||||
}
|
||||
|
||||
Point tv2image(Dimension pImageDim, Point2D point) {
|
||||
double tvFraction = (1.0 - 2*mBorderFraction);
|
||||
|
||||
double tvWidth = tvFraction * pImageDim.width;
|
||||
double tvXIndex = point.getX()*tvWidth;
|
||||
double imageXIndex = tvXIndex + mBorderFraction*pImageDim.width;
|
||||
|
||||
double tvHeight = tvFraction * pImageDim.height;
|
||||
double tvYIndex = point.getY()*tvHeight;
|
||||
double imageYIndex = tvYIndex + mBorderFraction*pImageDim.height;
|
||||
|
||||
return new Point((int)imageXIndex, (int)imageYIndex);
|
||||
}
|
||||
|
||||
private int determineColor(int xMin, int xMax, int yMin, int yMax) {
|
||||
int red = 0;
|
||||
int green = 0;
|
||||
int blue = 0;
|
||||
int count = 0;
|
||||
|
||||
for (int y = yMin; y <= yMax; ++y) {
|
||||
for (int x = xMin; x <= xMax; ++x) {
|
||||
int color = mTvImage.getRGB(x, y);
|
||||
red += (color >> 16) & 0xFF;
|
||||
green += (color >> 8) & 0xFF;
|
||||
blue += color & 0xFF;
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
return count > 0 ? new Color(red / count, green/count, blue/count).getRGB() : 0;
|
||||
}
|
||||
|
||||
private void paintAllLeds(Graphics2D g2d) {
|
||||
|
||||
for (int i=2; i<=180; i+=4) {
|
||||
if (isCancelled()) {
|
||||
return;
|
||||
}
|
||||
int arcSize = 24 + (int)((i/12.0)*(i/12.0));
|
||||
|
||||
for(LedPaint led : mLedPaints) {
|
||||
int argb = 0x05000000 | (0x00ffffff & led.color);
|
||||
g2d.setColor(new Color(argb , true));
|
||||
|
||||
g2d.translate(led.point.getX(), led.point.getY());
|
||||
g2d.rotate(led.angle_rad);
|
||||
g2d.fillArc(-arcSize, -arcSize, 2*arcSize, 2*arcSize, 90-(i/2), i);
|
||||
g2d.rotate(-led.angle_rad);
|
||||
g2d.translate(-led.point.getX(), -led.point.getY());
|
||||
|
||||
setProgress(10+i/3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,134 @@
|
||||
package org.hyperion.hypercon.gui;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseMotionListener;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.Vector;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
|
||||
import org.hyperion.hypercon.spec.Led;
|
||||
|
||||
public class LedTvComponent extends JComponent {
|
||||
|
||||
private final BufferedImage mDisplayedImage = new BufferedImage(1280, 720, BufferedImage.TYPE_INT_ARGB);
|
||||
private final Graphics2D mImageG2d = mDisplayedImage.createGraphics();
|
||||
|
||||
private final int mBorderWidth = 12;
|
||||
|
||||
private Vector<Led> mLeds;
|
||||
|
||||
private Led mSelectedLed;
|
||||
|
||||
public LedTvComponent(Vector<Led> pLeds) {
|
||||
mLeds = pLeds;
|
||||
|
||||
addMouseMotionListener(mMouseMotionListener);
|
||||
}
|
||||
|
||||
public void setLeds(Vector<Led> pLeds) {
|
||||
mLeds = pLeds;
|
||||
}
|
||||
|
||||
public void setImage(Image pImage) {
|
||||
mImageG2d.clearRect(0, 0, mDisplayedImage.getWidth(), mDisplayedImage.getHeight());
|
||||
mImageG2d.drawImage(pImage, 0,0, mDisplayedImage.getWidth(), mDisplayedImage.getHeight(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
Graphics2D g2d = (Graphics2D) g.create();
|
||||
|
||||
g2d.setColor(Color.DARK_GRAY.darker());
|
||||
g2d.fillRect(0,0, getWidth()-1, getHeight()-1);
|
||||
|
||||
g2d.drawImage(mDisplayedImage, mBorderWidth, mBorderWidth, getWidth()-2*mBorderWidth, getHeight()-2*mBorderWidth, null);
|
||||
if (mLeds == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
g2d.setColor(Color.GRAY);
|
||||
for (Led led : mLeds) {
|
||||
Rectangle rect = led2tv(led.mImageRectangle);
|
||||
|
||||
g2d.drawRect(rect.x, rect.y, rect.width, rect.height);
|
||||
|
||||
switch (led.mSide) {
|
||||
case top_left:
|
||||
g2d.drawString(""+led.mLedSeqNr, 0, 11);
|
||||
break;
|
||||
case top:
|
||||
g2d.drawString(""+led.mLedSeqNr, (int)rect.getCenterX(), 11);
|
||||
break;
|
||||
case top_right:
|
||||
g2d.drawString(""+led.mLedSeqNr, (int)getWidth()-11, (int)11);
|
||||
break;
|
||||
case right:
|
||||
g2d.drawString(""+led.mLedSeqNr, (int)getWidth()-11, (int)rect.getCenterY());
|
||||
break;
|
||||
case bottom_right:
|
||||
g2d.drawString(""+led.mLedSeqNr, (int)getWidth()-11, (int)getHeight()-1);
|
||||
break;
|
||||
case bottom:
|
||||
g2d.drawString(""+led.mLedSeqNr, (int)rect.getCenterX(), (int)getHeight()-1);
|
||||
break;
|
||||
case bottom_left:
|
||||
g2d.drawString(""+led.mLedSeqNr, (int)0, (int)getHeight()-1);
|
||||
break;
|
||||
case left:
|
||||
g2d.drawString(""+led.mLedSeqNr, 0, (int)rect.getCenterY());
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mSelectedLed != null) {
|
||||
Rectangle rect = led2tv(mSelectedLed.mImageRectangle);
|
||||
|
||||
g2d.setStroke(new BasicStroke(3.0f));
|
||||
g2d.setColor(Color.WHITE);
|
||||
g2d.drawRect(rect.x, rect.y, rect.width, rect.height);
|
||||
}
|
||||
}
|
||||
|
||||
public Rectangle led2tv(Rectangle2D pLedRect) {
|
||||
int tvWidth = getWidth()-2*mBorderWidth;
|
||||
int tvHeight = getHeight()-2*mBorderWidth;
|
||||
|
||||
int x = (int) Math.round(mBorderWidth + tvWidth*pLedRect.getX());
|
||||
int y = (int) Math.round(mBorderWidth + tvHeight*pLedRect.getY());
|
||||
int width = (int) Math.round(tvWidth * pLedRect.getWidth());
|
||||
int height = (int) Math.round(tvHeight * pLedRect.getHeight());
|
||||
|
||||
return new Rectangle(x,y, width, height);
|
||||
}
|
||||
|
||||
private final MouseMotionListener mMouseMotionListener = new MouseMotionListener() {
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
mSelectedLed = null;
|
||||
|
||||
double x = (double)(e.getX() - mBorderWidth) / (getWidth() - mBorderWidth*2);
|
||||
double y = (double)(e.getY() - mBorderWidth) / (getHeight() - mBorderWidth*2);
|
||||
|
||||
for (Led led : mLeds) {
|
||||
if (led.mImageRectangle.contains(x, y) || (Math.abs(led.mLocation.getX() - x) < 0.01 && Math.abs(led.mLocation.getY() - y) < 0.01)) {
|
||||
mSelectedLed = led;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
repaint();
|
||||
}
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user