From 2879f44f08450f21502d205b7fa2dc3fb5cf43e5 Mon Sep 17 00:00:00 2001 From: "T. van der Zwan" Date: Fri, 15 Nov 2013 22:26:31 +0100 Subject: [PATCH] Updated led simulation (little bit faster and behind a worker to keep gui responsive) Former-commit-id: 45d6a3d0243f5fb3a0bbcb03f2276e13b683c182 --- deploy/HyperCon.jar.REMOVED.git-id | 2 +- .../hyperion/hypercon/gui/ConfigPanel.java | 5 +- .../hyperion/hypercon/gui/ImageComponent.java | 27 ++ .../hyperion/hypercon/gui/JHyperionTv.java | 346 ------------------ .../hypercon/gui/LedSimulationComponent.java | 313 ++++++++++++++++ .../hypercon/gui/LedSimulationWorker.java | 135 +++++++ .../hyperion/hypercon/gui/LedTvComponent.java | 134 +++++++ 7 files changed, 612 insertions(+), 350 deletions(-) create mode 100644 src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/ImageComponent.java delete mode 100644 src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/JHyperionTv.java create mode 100644 src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/LedSimulationComponent.java create mode 100644 src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/LedSimulationWorker.java create mode 100644 src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/LedTvComponent.java diff --git a/deploy/HyperCon.jar.REMOVED.git-id b/deploy/HyperCon.jar.REMOVED.git-id index 7b781130..18459a93 100644 --- a/deploy/HyperCon.jar.REMOVED.git-id +++ b/deploy/HyperCon.jar.REMOVED.git-id @@ -1 +1 @@ -85ee9ddb3d9a3dd3ba63e1d1d8b21e3616cb79ae \ No newline at end of file +fb506ad21f8aabad449e751a8b48337d61be16eb \ No newline at end of file diff --git a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/ConfigPanel.java b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/ConfigPanel.java index 8fea85d7..6c56bc44 100644 --- a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/ConfigPanel.java +++ b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/ConfigPanel.java @@ -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; diff --git a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/ImageComponent.java b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/ImageComponent.java new file mode 100644 index 00000000..3984c814 --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/ImageComponent.java @@ -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); + } +} diff --git a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/JHyperionTv.java b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/JHyperionTv.java deleted file mode 100644 index bc71d7fc..00000000 --- a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/JHyperionTv.java +++ /dev/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 mLeds2 = new Vector<>(); - - public void setLeds(Vector pLeds) { - mLeds2.clear(); - - for (Led led : pLeds) { - mLeds2.add(new LedWrapper(led)); - } - } - - LedWrapper mSelLed = null; - - public JHyperionTv() { - - // Pre-cache the popup menu - new SwingWorker() { - @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 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); - } -} diff --git a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/LedSimulationComponent.java b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/LedSimulationComponent.java new file mode 100644 index 00000000..90461a78 --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/LedSimulationComponent.java @@ -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 pLeds) { + super(); + + initialise(pLeds); + + setLeds(pLeds); + } + + void initialise(Vector 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 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 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); + } + } + +} diff --git a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/LedSimulationWorker.java b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/LedSimulationWorker.java new file mode 100644 index 00000000..afe5edd2 --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/LedSimulationWorker.java @@ -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 { + + private final double mBorderFraction = 0.2; + + private final BufferedImage mTvImage; + + private final Vector mLeds; + + public LedSimulationWorker(BufferedImage pTvImage, Vector pLeds) { + super(); + + mTvImage = pTvImage; + mLeds = pLeds; + } + + class LedPaint { + int color; + + Point point; + double angle_rad; + } + + private final List 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); + } + } + } +} diff --git a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/LedTvComponent.java b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/LedTvComponent.java new file mode 100644 index 00000000..b31ab760 --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/LedTvComponent.java @@ -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 mLeds; + + private Led mSelectedLed; + + public LedTvComponent(Vector pLeds) { + mLeds = pLeds; + + addMouseMotionListener(mMouseMotionListener); + } + + public void setLeds(Vector 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) { + + } + }; + +}