diff --git a/src/config-tool/.gitignore b/src/config-tool/.gitignore new file mode 100644 index 00000000..e8d03113 --- /dev/null +++ b/src/config-tool/.gitignore @@ -0,0 +1 @@ +/.metadata diff --git a/src/config-tool/ConfigTool/.classpath b/src/config-tool/ConfigTool/.classpath new file mode 100644 index 00000000..cd43896c --- /dev/null +++ b/src/config-tool/ConfigTool/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/config-tool/ConfigTool/.gitignore b/src/config-tool/ConfigTool/.gitignore new file mode 100644 index 00000000..77237710 --- /dev/null +++ b/src/config-tool/ConfigTool/.gitignore @@ -0,0 +1,2 @@ +/.settings +/classes diff --git a/src/config-tool/ConfigTool/.project b/src/config-tool/ConfigTool/.project new file mode 100644 index 00000000..9e7af111 --- /dev/null +++ b/src/config-tool/ConfigTool/.project @@ -0,0 +1,17 @@ + + + ConfigTool + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/src/config-tool/ConfigTool/src/org/hyperion/config/HyperionConfigApplet.java b/src/config-tool/ConfigTool/src/org/hyperion/config/HyperionConfigApplet.java new file mode 100644 index 00000000..0b5292fe --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/config/HyperionConfigApplet.java @@ -0,0 +1,23 @@ +package org.hyperion.config; + +import java.awt.BorderLayout; +import java.awt.Dimension; + +import javax.swing.JApplet; + +import org.hyperion.config.gui.ConfigPanel; + +public class HyperionConfigApplet extends JApplet { + + public HyperionConfigApplet() { + super(); + + initialise(); + } + + private void initialise() { + setPreferredSize(new Dimension(600, 300)); + + add(new ConfigPanel(), BorderLayout.CENTER); + } +} diff --git a/src/config-tool/ConfigTool/src/org/hyperion/config/LedFrameFactory.java b/src/config-tool/ConfigTool/src/org/hyperion/config/LedFrameFactory.java new file mode 100644 index 00000000..af326191 --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/config/LedFrameFactory.java @@ -0,0 +1,165 @@ +package org.hyperion.config; + +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.Vector; + +import org.hyperion.config.spec.BorderSide; +import org.hyperion.config.spec.Led; +import org.hyperion.config.spec.LedFrameConstruction; + +public class LedFrameFactory { + + private static int increase(LedFrameConstruction frameSpec, int pLedCounter) { + if (frameSpec.clockwiseDirection) { + return (pLedCounter+1)%frameSpec.getLedCount(); + } else { + if (pLedCounter == 0) { + return frameSpec.getLedCount() - 1; + } + return pLedCounter -1; + } + + } + + public static Vector construct(LedFrameConstruction frameSpec) { + double overlap_frac = 0.50; + + Vector mLeds = new Vector<>(); + + int totalLedCount = frameSpec.getLedCount(); + if (totalLedCount <= 0) { + return mLeds; + } + + int iLed = (totalLedCount - frameSpec.firstLedOffset)%totalLedCount; + if (iLed < 0) { + iLed += totalLedCount; + } + if (frameSpec.topLeftCorner) { + mLeds.add(createLed(frameSpec, iLed, 0.0, 0.0, overlap_frac, BorderSide.top_left)); + iLed = increase(frameSpec, iLed); + } + if (frameSpec.topLedCnt > 0) { + int ledCnt = frameSpec.topLedCnt; + double ledSpacing = (double)1.0/(ledCnt); + for (int iTop=0; iTop 0) { + int ledCnt = frameSpec.rightLedCnt; + double ledSpacing = 1.0/ledCnt; + for (int iRight=0; iRight 0) { + int ledCnt = frameSpec.topLedCnt; + + double ledSpacing = (double)1.0/ledCnt; + for (int iBottom=(ledCnt-1); iBottom>=0; --iBottom) { + if (iBottom > (frameSpec.bottomLedCnt-1)/2 && iBottom < ledCnt - frameSpec.bottomLedCnt/2) { + continue; + } + double led_x = ledSpacing/2.0 + iBottom * ledSpacing; + double led_y = 1.0; + + mLeds.add(createLed(frameSpec, iLed, led_x, led_y, overlap_frac, BorderSide.bottom)); + iLed = increase(frameSpec, iLed); + } + } + if (frameSpec.bottomLeftCorner) { + mLeds.add(createLed(frameSpec, iLed, 0.0, 1.0, overlap_frac, BorderSide.bottom_left)); + iLed = increase(frameSpec, iLed); + } + if (frameSpec.leftLedCnt > 0) { + int ledCnt = frameSpec.leftLedCnt; + double ledSpacing = (double)1.0/ledCnt; + for (int iRight=(ledCnt-1); iRight>=0; --iRight) { + double led_x = 0.0; + double led_y = ledSpacing/2.0 + iRight * ledSpacing; + + mLeds.add(createLed(frameSpec, iLed, led_x, led_y, overlap_frac, BorderSide.left)); + iLed = increase(frameSpec, iLed); + } + } + + return mLeds; + } + + private static Led createLed(LedFrameConstruction frameSpec, int seqNr, double x_frac, double y_frac, double overlap_frac, BorderSide pBorderSide) { + Led led = new Led(); + led.mLedSeqNr = seqNr; + led.mLocation = new Point2D.Double(x_frac, y_frac); + led.mSide = pBorderSide; + + double widthFrac = (1.0/frameSpec.topLedCnt * (1.0 + overlap_frac))/2.0; + double heightFrac = (1.0/frameSpec.leftLedCnt * (1.0 + overlap_frac))/2.0; + + switch (pBorderSide) { + case top_left: { + led.mImageRectangle = new Rectangle2D.Double(0.0, 0.0, frameSpec.verticalDepth, frameSpec.horizontalDepth); + break; + } + case top_right: { + led.mImageRectangle = new Rectangle2D.Double(1.0-frameSpec.verticalDepth, 0.0, frameSpec.verticalDepth, frameSpec.horizontalDepth); + break; + } + case bottom_left: { + led.mImageRectangle = new Rectangle2D.Double(0.0, 1.0-frameSpec.horizontalDepth, frameSpec.verticalDepth, frameSpec.horizontalDepth); + break; + } + case bottom_right: { + led.mImageRectangle = new Rectangle2D.Double(1.0-frameSpec.verticalDepth, 1.0-frameSpec.horizontalDepth, frameSpec.verticalDepth, frameSpec.horizontalDepth); + break; + } + case top:{ + double intXmin_frac = Math.max(0.0, x_frac-widthFrac); + double intXmax_frac = Math.min(x_frac+widthFrac, 1.0); + led.mImageRectangle = new Rectangle2D.Double(intXmin_frac, 0.0, intXmax_frac-intXmin_frac, frameSpec.horizontalDepth); + + break; + } + case bottom: + { + double intXmin_frac = Math.max(0.0, x_frac-widthFrac); + double intXmax_frac = Math.min(x_frac+widthFrac, 1.0); + + led.mImageRectangle = new Rectangle2D.Double(intXmin_frac, 1.0-frameSpec.horizontalDepth, intXmax_frac-intXmin_frac, frameSpec.horizontalDepth); + break; + } + case left: { + double intYmin_frac = Math.max(0.0, y_frac-heightFrac); + double intYmax_frac = Math.min(y_frac+heightFrac, 1.0); + led.mImageRectangle = new Rectangle2D.Double(0.0, intYmin_frac, frameSpec.verticalDepth, intYmax_frac-intYmin_frac); + break; + } + case right: + double intYmin_frac = Math.max(0.0, y_frac-heightFrac); + double intYmax_frac = Math.min(y_frac+heightFrac, 1.0); + led.mImageRectangle = new Rectangle2D.Double(1.0-frameSpec.verticalDepth, intYmin_frac, frameSpec.verticalDepth, intYmax_frac-intYmin_frac); + break; + } + + return led; + } + + +} diff --git a/src/config-tool/ConfigTool/src/org/hyperion/config/LedString.java b/src/config-tool/ConfigTool/src/org/hyperion/config/LedString.java new file mode 100644 index 00000000..c7d3d68f --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/config/LedString.java @@ -0,0 +1,74 @@ +package org.hyperion.config; + +import java.io.FileWriter; +import java.io.IOException; +import java.util.Locale; +import java.util.Vector; + +import org.hyperion.config.spec.ColorConfig; +import org.hyperion.config.spec.DeviceConfig; +import org.hyperion.config.spec.Led; +import org.hyperion.config.spec.MiscConfig; + +public class LedString { + /** The individual led configuration */ + public Vector leds; + + /** The configuration of the output device */ + DeviceConfig mDeviceConfig = new DeviceConfig(); + + /** The color adjustment configuration */ + ColorConfig mColorConfig = new ColorConfig(); + + /** The miscellaneous configuration (bootsequence, blackborder detector, etc) */ + MiscConfig mMiscConfig = new MiscConfig(); + + public void saveConfigFile(String mFilename) throws IOException { + + try (FileWriter fw = new FileWriter(mFilename)) { + fw.write("// Automatically generated configuration file for 'Hyperion'\n"); + fw.write("// Generated by: 'Hyperion configuration Tool\n"); + fw.write("\n"); + fw.write("{\n"); + + String deviceJson = mDeviceConfig.toJsonString(); + fw.write(deviceJson + ",\n"); + + String colorJson = mColorConfig.toJsonString(); + fw.write(colorJson + ",\n"); + + String ledJson = ledToJsonString(); + fw.write(ledJson + ",\n"); + + String miscJson = mMiscConfig.toJsonString(); + fw.write(miscJson + "\n"); + + fw.write("}\n"); + } catch (IOException e) { + throw e; + } + } + + String ledToJsonString() { + StringBuffer strBuf = new StringBuffer(); + strBuf.append("\t\"leds\" : \n"); + strBuf.append("\t[\n"); + + for (Led led : leds) + { + strBuf.append("\t\t{\n"); + strBuf.append(String.format(Locale.ROOT, "\t\t\t\"index\" : %d,\n", led.mLedSeqNr)); + strBuf.append(String.format(Locale.ROOT, "\t\t\t\"hscan\" : { \"minimum\" : %.4f, \"maximum\" : %.4f },\n", led.mImageRectangle.getMinX(), led.mImageRectangle.getMaxX())); + strBuf.append(String.format(Locale.ROOT, "\t\t\t\"vscan\" : { \"minimum\" : %.4f, \"maximum\" : %.4f }\n", led.mImageRectangle.getMinY(), led.mImageRectangle.getMaxY())); + if (led != leds.lastElement()) { + strBuf.append("\t\t},\n"); + } else { + strBuf.append("\t\t}\n"); + } + } + + strBuf.append("\t]"); + + return strBuf.toString(); + } +} diff --git a/src/config-tool/ConfigTool/src/org/hyperion/config/Main.java b/src/config-tool/ConfigTool/src/org/hyperion/config/Main.java new file mode 100644 index 00000000..2405c8df --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/config/Main.java @@ -0,0 +1,24 @@ +package org.hyperion.config; + +import javax.swing.JFrame; +import javax.swing.UIManager; + +import org.hyperion.config.gui.ConfigPanel; + +public class Main { + + public static void main(String[] pArgs) { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (Exception e) {} + + JFrame frame = new JFrame(); + frame.setTitle("Hyperion configuration Tool"); + frame.setSize(1300, 600); + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + + frame.setContentPane(new ConfigPanel()); + + frame.setVisible(true); + } +} diff --git a/src/config-tool/ConfigTool/src/org/hyperion/config/gui/ColorConfigPanel.java b/src/config-tool/ConfigTool/src/org/hyperion/config/gui/ColorConfigPanel.java new file mode 100644 index 00000000..31b66e5b --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/config/gui/ColorConfigPanel.java @@ -0,0 +1,209 @@ +package org.hyperion.config.gui; + +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.GroupLayout; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JSpinner; +import javax.swing.SpinnerNumberModel; + +public class ColorConfigPanel extends JPanel { + private JPanel mRgbTransformPanel; + private JLabel mThresholdLabel; + private JLabel mGammaLabel; + private JLabel mBlacklevelLabel; + private JLabel mWhitelevelLabel; + private JLabel mRedTransformLabel; + private JSpinner mRedThresholdSpinner; + private JSpinner mRedGammaSpinner; + private JSpinner mRedBlacklevelSpinner; + private JSpinner mRedWhitelevelSpinner; + private JLabel mGreenTransformLabel; + private JSpinner mGreenThresholdSpinner; + private JSpinner mGreenGammaSpinner; + private JSpinner mGreenBlacklevelSpinner; + private JSpinner mGreenWhitelevelSpinner; + private JLabel mBlueTransformLabel; + private JSpinner mBlueThresholdSpinner; + private JSpinner mBlueGammaSpinner; + private JSpinner mBlueBlacklevelSpinner; + private JSpinner mBlueWhitelevelSpinner; + + private JPanel mHsvTransformPanel; + private JLabel mSaturationAdjustLabel; + private JSpinner mSaturationAdjustSpinner; + private JLabel mValueAdjustLabel; + private JSpinner mValueAdjustSpinner; + + public ColorConfigPanel() { + super(); + + initialise(); + } + + private void initialise() { + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + + add(getRgbPanel()); + add(getHsvPanel()); + } + + private JPanel getRgbPanel() { + if (mRgbTransformPanel == null) { + mRgbTransformPanel = new JPanel(); + + GroupLayout layout = new GroupLayout(mRgbTransformPanel); + mRgbTransformPanel.setLayout(layout); + + mThresholdLabel = new JLabel("Thresold"); + mRgbTransformPanel.add(mThresholdLabel); + + mGammaLabel = new JLabel("Gamma"); + mRgbTransformPanel.add(mGammaLabel); + + mBlacklevelLabel = new JLabel("Blacklevel"); + mRgbTransformPanel.add(mBlacklevelLabel); + + mWhitelevelLabel = new JLabel("Whitelevel"); + mRgbTransformPanel.add(mWhitelevelLabel); + + mRedTransformLabel = new JLabel("RED"); + mRgbTransformPanel.add(mRedTransformLabel); + mRedThresholdSpinner = new JSpinner(new SpinnerNumberModel()); + mRgbTransformPanel.add(mRedThresholdSpinner); + mRedGammaSpinner = new JSpinner(new SpinnerNumberModel()); + mRgbTransformPanel.add(mRedGammaSpinner); + mRedBlacklevelSpinner = new JSpinner(new SpinnerNumberModel()); + mRgbTransformPanel.add(mRedBlacklevelSpinner); + mRedWhitelevelSpinner = new JSpinner(new SpinnerNumberModel()); + mRgbTransformPanel.add(mRedWhitelevelSpinner); + + mGreenTransformLabel = new JLabel("GREEN"); + mRgbTransformPanel.add(mGreenTransformLabel); + mGreenThresholdSpinner = new JSpinner(new SpinnerNumberModel()); + mRgbTransformPanel.add(mGreenThresholdSpinner); + mGreenGammaSpinner = new JSpinner(new SpinnerNumberModel()); + mRgbTransformPanel.add(mGreenGammaSpinner); + mGreenBlacklevelSpinner = new JSpinner(new SpinnerNumberModel()); + mRgbTransformPanel.add(mGreenBlacklevelSpinner); + mGreenWhitelevelSpinner = new JSpinner(new SpinnerNumberModel()); + mRgbTransformPanel.add(mGreenWhitelevelSpinner); + + mBlueTransformLabel = new JLabel("BLUE"); + mRgbTransformPanel.add(mBlueTransformLabel); + mBlueThresholdSpinner = new JSpinner(new SpinnerNumberModel()); + mRgbTransformPanel.add(mBlueThresholdSpinner); + mBlueGammaSpinner = new JSpinner(new SpinnerNumberModel()); + mRgbTransformPanel.add(mBlueGammaSpinner); + mBlueBlacklevelSpinner = new JSpinner(new SpinnerNumberModel()); + mRgbTransformPanel.add(mBlueBlacklevelSpinner); + mBlueWhitelevelSpinner = new JSpinner(new SpinnerNumberModel()); + mRgbTransformPanel.add(mBlueWhitelevelSpinner); + + layout.setHorizontalGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup() + .addComponent(mRedTransformLabel) + .addComponent(mGreenTransformLabel) + .addComponent(mBlueTransformLabel)) + .addGroup(layout.createParallelGroup() + .addComponent(mThresholdLabel) + .addComponent(mRedThresholdSpinner) + .addComponent(mGreenThresholdSpinner) + .addComponent(mBlueThresholdSpinner)) + .addGroup(layout.createParallelGroup() + .addComponent(mGammaLabel) + .addComponent(mRedGammaSpinner) + .addComponent(mGreenGammaSpinner) + .addComponent(mBlueGammaSpinner) + ) + .addGroup(layout.createParallelGroup() + .addComponent(mBlacklevelLabel) + .addComponent(mRedBlacklevelSpinner) + .addComponent(mGreenBlacklevelSpinner) + .addComponent(mBlueBlacklevelSpinner) + ) + .addGroup(layout.createParallelGroup() + .addComponent(mWhitelevelLabel) + .addComponent(mRedWhitelevelSpinner) + .addComponent(mGreenWhitelevelSpinner) + .addComponent(mBlueWhitelevelSpinner) + )); + + layout.setVerticalGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup() + .addComponent(mThresholdLabel) + .addComponent(mGammaLabel) + .addComponent(mBlacklevelLabel) + .addComponent(mWhitelevelLabel)) + .addGroup(layout.createParallelGroup() + .addComponent(mRedTransformLabel) + .addComponent(mRedThresholdSpinner) + .addComponent(mRedGammaSpinner) + .addComponent(mRedBlacklevelSpinner) + .addComponent(mRedWhitelevelSpinner) + ) + .addGroup(layout.createParallelGroup() + .addComponent(mGreenTransformLabel) + .addComponent(mGreenThresholdSpinner) + .addComponent(mGreenGammaSpinner) + .addComponent(mGreenBlacklevelSpinner) + .addComponent(mGreenWhitelevelSpinner) + ) + .addGroup(layout.createParallelGroup() + .addComponent(mBlueTransformLabel) + .addComponent(mBlueThresholdSpinner) + .addComponent(mBlueGammaSpinner) + .addComponent(mBlueBlacklevelSpinner) + .addComponent(mBlueWhitelevelSpinner) + )); + } + return mRgbTransformPanel; + } + + private JPanel getHsvPanel() { + if (mHsvTransformPanel == null) { + mHsvTransformPanel = new JPanel(); + mHsvTransformPanel.setBorder(BorderFactory.createTitledBorder("HSV")); + + GroupLayout layout = new GroupLayout(mHsvTransformPanel); + mHsvTransformPanel.setLayout(layout); + + mSaturationAdjustLabel = new JLabel("Saturation"); + mHsvTransformPanel.add(mSaturationAdjustLabel); + + mSaturationAdjustSpinner = new JSpinner(new SpinnerNumberModel(1.0, 0.0, 1024.0, 0.01)); + mHsvTransformPanel.add(mSaturationAdjustSpinner); + + mValueAdjustLabel = new JLabel("Value"); + mHsvTransformPanel.add(mValueAdjustLabel); + + mValueAdjustSpinner = new JSpinner(new SpinnerNumberModel(1.0, 0.0, 1024.0, 0.01)); + mHsvTransformPanel.add(mValueAdjustSpinner); + + layout.setHorizontalGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup() + .addComponent(mSaturationAdjustLabel) + .addComponent(mValueAdjustLabel) + ) + .addGroup(layout.createParallelGroup() + .addComponent(mSaturationAdjustSpinner) + .addComponent(mValueAdjustSpinner) + ) + ); + + layout.setVerticalGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup() + .addComponent(mSaturationAdjustLabel) + .addComponent(mSaturationAdjustSpinner) + ) + .addGroup(layout.createParallelGroup() + .addComponent(mValueAdjustLabel) + .addComponent(mValueAdjustSpinner) + ) + ); + } + return mHsvTransformPanel; + } + +} diff --git a/src/config-tool/ConfigTool/src/org/hyperion/config/gui/ConfigPanel.java b/src/config-tool/ConfigTool/src/org/hyperion/config/gui/ConfigPanel.java new file mode 100644 index 00000000..cb2bf78b --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/config/gui/ConfigPanel.java @@ -0,0 +1,206 @@ +package org.hyperion.config.gui; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.io.IOException; +import java.util.Observable; +import java.util.Observer; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.GroupLayout; +import javax.swing.JButton; +import javax.swing.JFileChooser; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JSpinner; +import javax.swing.SpinnerNumberModel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import org.hyperion.config.LedFrameFactory; +import org.hyperion.config.LedString; +import org.hyperion.config.spec.LedFrameConstruction; + +public class ConfigPanel extends JPanel { + + private final LedFrameConstruction mLedFrameSpec = new LedFrameConstruction(); + + private final Action mSaveConfigAction = new AbstractAction("Create Hyperion Configuration") { + @Override + public void actionPerformed(ActionEvent e) { + JFileChooser fileChooser = new JFileChooser(); + fileChooser.showSaveDialog(ConfigPanel.this); + + LedString ledString = new LedString(); + ledString.leds = LedFrameFactory.construct(mLedFrameSpec); + + try { + ledString.saveConfigFile(fileChooser.getSelectedFile().getAbsolutePath()); + } catch (IOException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + } + }; + + private JPanel mTvPanel; + private JHyperionTv mHyperionTv; + + private JPanel mConstructionPanel; + + private JPanel mIntegrationPanel; + + private JLabel mHorizontalDepthLabel; + private JSpinner mHorizontalDepthSpinner; + private JLabel mVerticalDepthLabel; + private JSpinner mVerticalDepthSpinner; + + private JPanel mSpecificationPanel; + + private MiscConfigPanel mMiscPanel; + + private JButton mSaveConfigButton; + + public ConfigPanel() { + super(); + + mLedFrameSpec.clockwiseDirection = true; + + mLedFrameSpec.topLeftCorner = true; + mLedFrameSpec.topRightCorner= true; + mLedFrameSpec.bottomLeftCorner= true; + mLedFrameSpec.bottomRightCorner= true; + + mLedFrameSpec.topLedCnt = 16; + mLedFrameSpec.bottomLedCnt = 16; + mLedFrameSpec.leftLedCnt = 7; + mLedFrameSpec.rightLedCnt = 7; + + mLedFrameSpec.firstLedOffset = 0; + + initialise(); + + mHyperionTv.setLeds(LedFrameFactory.construct(mLedFrameSpec)); + mLedFrameSpec.addObserver(new Observer() { + @Override + public void update(Observable o, Object arg) { + mHyperionTv.setLeds(LedFrameFactory.construct(mLedFrameSpec)); + mHyperionTv.repaint(); + } + }); + } + + private void initialise() { + setLayout(new BorderLayout()); + + add(getTvPanel(), BorderLayout.CENTER); + add(getSpecificationPanel(), BorderLayout.WEST); + + } + + private JPanel getTvPanel() { + if (mTvPanel == null) { + mTvPanel = new JPanel(); + mTvPanel.setLayout(new BorderLayout()); + + mHyperionTv = new JHyperionTv(); + mTvPanel.add(mHyperionTv, BorderLayout.CENTER); + } + return mTvPanel; + } + + private JPanel getSpecificationPanel() { + if (mSpecificationPanel == null) { + mSpecificationPanel = new JPanel(); + mSpecificationPanel.setPreferredSize(new Dimension(300, 200)); + mSpecificationPanel.setLayout(new BoxLayout(mSpecificationPanel, BoxLayout.Y_AXIS)); + + mConstructionPanel = new LedFramePanel(mLedFrameSpec); + mConstructionPanel.setBorder(BorderFactory.createTitledBorder("Construction")); + mSpecificationPanel.add(mConstructionPanel); + + mSpecificationPanel.add(getIntegrationPanel()); + + mMiscPanel = new MiscConfigPanel(); + mMiscPanel.setBorder(BorderFactory.createTitledBorder("Misc")); + mSpecificationPanel.add(mMiscPanel); + + JPanel panel = new JPanel(new BorderLayout()); + panel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); + mSaveConfigButton = new JButton(mSaveConfigAction); + panel.add(mSaveConfigButton, BorderLayout.SOUTH); + mSpecificationPanel.add(panel); + } + return mSpecificationPanel; + } + + private JPanel getIntegrationPanel() { + if (mIntegrationPanel == null) { + mIntegrationPanel = new JPanel(); + mIntegrationPanel.setBorder(BorderFactory.createTitledBorder("Image Process")); + + mHorizontalDepthLabel = new JLabel("Horizontal depth:"); + mHorizontalDepthLabel.setPreferredSize(new Dimension(100, 30)); + mHorizontalDepthLabel.setMaximumSize(new Dimension(150, 30)); + mIntegrationPanel.add(mHorizontalDepthLabel); + + mHorizontalDepthSpinner = new JSpinner(new SpinnerNumberModel(0.05, 0.01, 1.0, 0.01)); + mHorizontalDepthSpinner.setPreferredSize(new Dimension(150, 30)); + mHorizontalDepthSpinner.setMaximumSize(new Dimension(250, 30)); + mHorizontalDepthSpinner.addChangeListener(mChangeListener); + mIntegrationPanel.add(mHorizontalDepthSpinner); + + mVerticalDepthLabel = new JLabel("Vertical depth:"); + mVerticalDepthLabel.setPreferredSize(new Dimension(100, 30)); + mVerticalDepthLabel.setMaximumSize(new Dimension(150, 30)); + mIntegrationPanel.add(mVerticalDepthLabel); + + mVerticalDepthSpinner = new JSpinner(new SpinnerNumberModel(0.05, 0.01, 1.0, 0.01)); + mVerticalDepthSpinner.setPreferredSize(new Dimension(150, 30)); + mVerticalDepthSpinner.setMaximumSize(new Dimension(250, 30)); + mVerticalDepthSpinner.addChangeListener(mChangeListener); + mIntegrationPanel.add(mVerticalDepthSpinner); + + GroupLayout layout = new GroupLayout(mIntegrationPanel); + mIntegrationPanel.setLayout(layout); + + layout.setHorizontalGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup() + .addComponent(mHorizontalDepthLabel) + .addComponent(mVerticalDepthLabel) + ) + .addGroup(layout.createParallelGroup() + .addComponent(mHorizontalDepthSpinner) + .addComponent(mVerticalDepthSpinner) + ) + ); + layout.setVerticalGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup() + .addComponent(mHorizontalDepthLabel) + .addComponent(mHorizontalDepthSpinner) + ) + .addGroup(layout.createParallelGroup() + .addComponent(mVerticalDepthLabel) + .addComponent(mVerticalDepthSpinner) + ) + ); + + } + return mIntegrationPanel; + } + + private final ChangeListener mChangeListener = new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + mLedFrameSpec.horizontalDepth = (Double)mHorizontalDepthSpinner.getValue(); + mLedFrameSpec.verticalDepth = (Double)mVerticalDepthSpinner.getValue(); + + mLedFrameSpec.setChanged(); + mLedFrameSpec.notifyObservers(); + } + }; +} diff --git a/src/config-tool/ConfigTool/src/org/hyperion/config/gui/JHyperionTv.java b/src/config-tool/ConfigTool/src/org/hyperion/config/gui/JHyperionTv.java new file mode 100644 index 00000000..6500e7c2 --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/config/gui/JHyperionTv.java @@ -0,0 +1,333 @@ +package org.hyperion.config.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.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 org.hyperion.config.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 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 + getPopupMenu(); + + 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)); + } + } + + 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(); + + 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/config/gui/LedFramePanel.java b/src/config-tool/ConfigTool/src/org/hyperion/config/gui/LedFramePanel.java new file mode 100644 index 00000000..0197d453 --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/config/gui/LedFramePanel.java @@ -0,0 +1,219 @@ +package org.hyperion.config.gui; + +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.GroupLayout; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JSpinner; +import javax.swing.SpinnerNumberModel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import org.hyperion.config.spec.DeviceType; +import org.hyperion.config.spec.LedFrameConstruction; + +public class LedFramePanel extends JPanel { + + private final LedFrameConstruction mLedFrameSpec; + + private JLabel mTypeLabel; + private JComboBox mTypeCombo; + + private JLabel mHorizontalCountLabel; + private JSpinner mHorizontalCountSpinner; + private JLabel mBottomGapCountLabel; + private JSpinner mBottomGapCountSpinner; + + private JLabel mVerticalCountLabel; + private JSpinner mVerticalCountSpinner; + + private JLabel mTopCornerLabel; + private JComboBox mTopCornerCombo; + private JLabel mBottomCornerLabel; + private JComboBox mBottomCornerCombo; + + private JLabel mDirectionLabel; + private JComboBox mDirectionCombo; + + private JLabel mOffsetLabel; + private JSpinner mOffsetSpinner; + + public LedFramePanel(LedFrameConstruction ledFrameSpec) { + super(); + + mLedFrameSpec = ledFrameSpec; + + initialise(); + } + + private void initialise() { + mTypeLabel = new JLabel("LED Type:"); + mTypeLabel.setPreferredSize(new Dimension(100, 30)); + mTypeLabel.setMaximumSize(new Dimension(150, 30)); + add(mTypeLabel); + mTypeCombo = new JComboBox<>(DeviceType.values()); + mTypeCombo.addActionListener(mActionListener); + mTypeCombo.setPreferredSize(new Dimension(150, 30)); + mTypeCombo.setMaximumSize(new Dimension(250, 30)); + add(mTypeCombo); + + mTopCornerLabel = new JLabel("Led in top corners"); + mTopCornerLabel.setPreferredSize(new Dimension(100, 30)); + mTopCornerLabel.setMaximumSize(new Dimension(150, 30)); + add(mTopCornerLabel); + mTopCornerCombo = new JComboBox<>(new Boolean[] {true, false}); + mTopCornerCombo.addActionListener(mActionListener); + mTopCornerCombo.setPreferredSize(new Dimension(150, 30)); + mTopCornerCombo.setMaximumSize(new Dimension(250, 30)); + add(mTopCornerCombo); + + mBottomCornerLabel = new JLabel("Led in bottom corners"); + mBottomCornerLabel.setPreferredSize(new Dimension(100, 30)); + mBottomCornerLabel.setMaximumSize(new Dimension(150, 30)); + add(mBottomCornerLabel); + mBottomCornerCombo = new JComboBox<>(new Boolean[] {true, false}); + mBottomCornerCombo.addActionListener(mActionListener); + mBottomCornerCombo.setPreferredSize(new Dimension(150, 30)); + mBottomCornerCombo.setMaximumSize(new Dimension(250, 30)); + add(mBottomCornerCombo); + + mDirectionLabel = new JLabel("Direction"); + mDirectionLabel.setPreferredSize(new Dimension(100, 30)); + mDirectionLabel.setMaximumSize(new Dimension(150, 30)); + add(mDirectionLabel); + mDirectionCombo = new JComboBox<>(LedFrameConstruction.Direction.values()); + mDirectionCombo.addActionListener(mActionListener); + mDirectionCombo.setPreferredSize(new Dimension(150, 30)); + mDirectionCombo.setMaximumSize(new Dimension(250, 30)); + add(mDirectionCombo); + + mHorizontalCountLabel = new JLabel("Horizontal #:"); + mHorizontalCountLabel.setPreferredSize(new Dimension(100, 30)); + mHorizontalCountLabel.setMaximumSize(new Dimension(150, 30)); + add(mHorizontalCountLabel); + mHorizontalCountSpinner = new JSpinner(new SpinnerNumberModel(mLedFrameSpec.topLedCnt, 0, 1024, 1)); + mHorizontalCountSpinner.addChangeListener(mChangeListener); + mHorizontalCountSpinner.setPreferredSize(new Dimension(150, 30)); + mHorizontalCountSpinner.setMaximumSize(new Dimension(250, 30)); + add(mHorizontalCountSpinner); + + mBottomGapCountLabel = new JLabel("Bottom Gap #:"); + mBottomGapCountLabel.setPreferredSize(new Dimension(100, 30)); + mBottomGapCountLabel.setMaximumSize(new Dimension(150, 30)); + add(mBottomGapCountLabel); + mBottomGapCountSpinner = new JSpinner(new SpinnerNumberModel(mLedFrameSpec.topLedCnt - mLedFrameSpec.bottomLedCnt, 0, 1024, 1)); + mBottomGapCountSpinner.addChangeListener(mChangeListener); + mBottomGapCountSpinner.setPreferredSize(new Dimension(150, 30)); + mBottomGapCountSpinner.setMaximumSize(new Dimension(250, 30)); + add(mBottomGapCountSpinner); + + mVerticalCountLabel = new JLabel("Vertical #:"); + mVerticalCountLabel.setPreferredSize(new Dimension(100, 30)); + mVerticalCountLabel.setMaximumSize(new Dimension(150, 30)); + add(mVerticalCountLabel); + mVerticalCountSpinner = new JSpinner(new SpinnerNumberModel(mLedFrameSpec.rightLedCnt, 0, 1024, 1)); + mVerticalCountSpinner.addChangeListener(mChangeListener); + mVerticalCountSpinner.setPreferredSize(new Dimension(150, 30)); + mVerticalCountSpinner.setMaximumSize(new Dimension(250, 30)); + add(mVerticalCountSpinner); + + mOffsetLabel = new JLabel("1st LED offset"); + mOffsetLabel.setPreferredSize(new Dimension(100, 30)); + mOffsetLabel.setMaximumSize(new Dimension(150, 30)); + add(mOffsetLabel); + mOffsetSpinner = new JSpinner(new SpinnerNumberModel(mLedFrameSpec.firstLedOffset, Integer.MIN_VALUE, Integer.MAX_VALUE, 1)); + mOffsetSpinner.addChangeListener(mChangeListener); + mOffsetSpinner.setPreferredSize(new Dimension(150, 30)); + mOffsetSpinner.setMaximumSize(new Dimension(250, 30)); + add(mOffsetSpinner); + + GroupLayout layout = new GroupLayout(this); + layout.setAutoCreateGaps(true); + setLayout(layout); + + layout.setHorizontalGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup() + .addComponent(mTypeLabel) + .addComponent(mDirectionLabel) + .addComponent(mTopCornerLabel) + .addComponent(mBottomCornerLabel) + .addComponent(mHorizontalCountLabel) + .addComponent(mBottomGapCountLabel) + .addComponent(mVerticalCountLabel) + .addComponent(mOffsetLabel)) + .addGroup(layout.createParallelGroup() + .addComponent(mTypeCombo) + .addComponent(mDirectionCombo) + .addComponent(mTopCornerCombo) + .addComponent(mBottomCornerCombo) + .addComponent(mHorizontalCountSpinner) + .addComponent(mBottomGapCountSpinner) + .addComponent(mVerticalCountSpinner) + .addComponent(mOffsetSpinner)) + ); + layout.setVerticalGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup() + .addComponent(mTypeLabel) + .addComponent(mTypeCombo)) + .addGroup(layout.createParallelGroup() + .addComponent(mDirectionLabel) + .addComponent(mDirectionCombo)) + .addGroup(layout.createParallelGroup() + .addComponent(mTopCornerLabel) + .addComponent(mTopCornerCombo)) + .addGroup(layout.createParallelGroup() + .addComponent(mBottomCornerLabel) + .addComponent(mBottomCornerCombo)) + .addGroup(layout.createParallelGroup() + .addComponent(mHorizontalCountLabel) + .addComponent(mHorizontalCountSpinner)) + .addGroup(layout.createParallelGroup() + .addComponent(mVerticalCountLabel) + .addComponent(mVerticalCountSpinner)) + .addGroup(layout.createParallelGroup() + .addComponent(mBottomGapCountLabel) + .addComponent(mBottomGapCountSpinner)) + .addGroup(layout.createParallelGroup() + .addComponent(mOffsetLabel) + .addComponent(mOffsetSpinner))); + + } + + void updateLedConstruction() { + mLedFrameSpec.topLeftCorner = (Boolean)mTopCornerCombo.getSelectedItem(); + mLedFrameSpec.topRightCorner = (Boolean)mTopCornerCombo.getSelectedItem(); + mLedFrameSpec.bottomLeftCorner = (Boolean)mBottomCornerCombo.getSelectedItem(); + mLedFrameSpec.bottomRightCorner = (Boolean)mBottomCornerCombo.getSelectedItem(); + + mLedFrameSpec.clockwiseDirection = ((LedFrameConstruction.Direction)mDirectionCombo.getSelectedItem()) == LedFrameConstruction.Direction.clockwise; + mLedFrameSpec.firstLedOffset = (Integer)mOffsetSpinner.getValue(); + + mLedFrameSpec.topLedCnt = (Integer)mHorizontalCountSpinner.getValue(); + mLedFrameSpec.bottomLedCnt = Math.max(0, mLedFrameSpec.topLedCnt - (Integer)mBottomGapCountSpinner.getValue()); + mLedFrameSpec.rightLedCnt = (Integer)mVerticalCountSpinner.getValue(); + mLedFrameSpec.leftLedCnt = (Integer)mVerticalCountSpinner.getValue(); + + mLedFrameSpec.setChanged(); + mLedFrameSpec.notifyObservers(); + + mBottomGapCountSpinner.setValue(mLedFrameSpec.topLedCnt - mLedFrameSpec.bottomLedCnt); + } + + private final ActionListener mActionListener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + updateLedConstruction(); + } + }; + private final ChangeListener mChangeListener = new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + updateLedConstruction(); + } + }; + +} diff --git a/src/config-tool/ConfigTool/src/org/hyperion/config/gui/MiscConfigPanel.java b/src/config-tool/ConfigTool/src/org/hyperion/config/gui/MiscConfigPanel.java new file mode 100644 index 00000000..5146b62c --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/config/gui/MiscConfigPanel.java @@ -0,0 +1,142 @@ +package org.hyperion.config.gui; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.GroupLayout; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JPanel; + +import org.hyperion.config.spec.BootSequence; + +public class MiscConfigPanel extends JPanel { + + private JLabel mMenuLabel; + private JComboBox mMenuCombo; + private JLabel mVideoLabel; + private JComboBox mVideoCombo; + private JLabel mPictureLabel; + private JComboBox mPictureCombo; + private JLabel mAudioLabel; + private JComboBox mAudioCombo; + + private JLabel mBlackborderDetectorLabel; + private JComboBox mBlackborderDetectorCombo; + private JLabel mBootSequenceLabel; + private JComboBox mBootSequenceCombo; + + public MiscConfigPanel() { + super(); + + initialise(); + } + + private void initialise() { + GroupLayout layout = new GroupLayout(this); + layout.setAutoCreateGaps(true); + setLayout(layout); + + mMenuLabel = new JLabel("XBMC Menu"); + add(mMenuLabel); + + mMenuCombo = new JComboBox<>(new String[] {"On", "Off"}); + mMenuCombo.setSelectedItem("Off"); + mMenuCombo.setToolTipText("Enables('On') or disbales('Off') the ambi-light in the XBMC Menu"); + mMenuCombo.addActionListener(mActionListener); + add(mMenuCombo); + + mVideoLabel = new JLabel("Video"); + add(mVideoLabel); + + mVideoCombo = new JComboBox<>(new String[] {"On", "Off"}); + mVideoCombo.setSelectedItem("On"); + mVideoCombo.setToolTipText("Enables('On') or disbales('Off') the ambi-light during video playback"); + mVideoCombo.addActionListener(mActionListener); + add(mVideoCombo); + + mPictureLabel = new JLabel("Picture"); + add(mPictureLabel); + + mPictureCombo = new JComboBox<>(new String[] {"On", "Off"}); + mPictureCombo.setSelectedItem("Off"); + mPictureCombo.setToolTipText("Enables('On') or disbales('Off') the ambi-light when viewing pictures"); + mPictureCombo.addActionListener(mActionListener); + add(mPictureCombo); + + mAudioLabel = new JLabel("Audio"); + add(mAudioLabel); + + mAudioCombo = new JComboBox<>(new String[] {"On", "Off"}); + mAudioCombo.setSelectedItem("Off"); + mAudioCombo.setToolTipText("Enables('On') or disbales('Off') the ambi-light when listing to audio"); + mAudioCombo.addActionListener(mActionListener); + add(mAudioCombo); + + mBlackborderDetectorLabel = new JLabel("Blackborder Detector:"); + add(mBlackborderDetectorLabel); + + mBlackborderDetectorCombo = new JComboBox<>(new String[] {"On", "Off"}); + mBlackborderDetectorCombo.setSelectedItem("On"); + mBlackborderDetectorCombo.setToolTipText("Enables or disables the blackborder detection and removal"); + add(mBlackborderDetectorCombo); + + mBootSequenceLabel = new JLabel("Boot Sequence:"); + add(mBootSequenceLabel); + + mBootSequenceCombo = new JComboBox<>(BootSequence.values()); + mBootSequenceCombo.setSelectedItem(BootSequence.rainbow); + mBootSequenceCombo.setToolTipText("The sequence used on startup to verify proper working of all the leds"); + add(mBootSequenceCombo); + + layout.setHorizontalGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup() + .addComponent(mMenuLabel) + .addComponent(mVideoLabel) + .addComponent(mPictureLabel) + .addComponent(mAudioLabel) + .addComponent(mBlackborderDetectorLabel) + .addComponent(mBootSequenceLabel) + ) + .addGroup(layout.createParallelGroup() + .addComponent(mMenuCombo) + .addComponent(mVideoCombo) + .addComponent(mPictureCombo) + .addComponent(mAudioCombo) + .addComponent(mBlackborderDetectorCombo) + .addComponent(mBootSequenceCombo) + )); + layout.setVerticalGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup() + .addComponent(mMenuLabel) + .addComponent(mMenuCombo) + ) + .addGroup(layout.createParallelGroup() + .addComponent(mVideoLabel) + .addComponent(mVideoCombo) + ) + .addGroup(layout.createParallelGroup() + .addComponent(mPictureLabel) + .addComponent(mPictureCombo) + ) + .addGroup(layout.createParallelGroup() + .addComponent(mAudioLabel) + .addComponent(mAudioCombo) + ) + .addGroup(layout.createParallelGroup() + .addComponent(mBlackborderDetectorLabel) + .addComponent(mBlackborderDetectorCombo) + ) + .addGroup(layout.createParallelGroup() + .addComponent(mBootSequenceLabel) + .addComponent(mBootSequenceCombo) + )); + } + + private final ActionListener mActionListener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + + } + }; +} diff --git a/src/config-tool/ConfigTool/src/org/hyperion/config/gui/TestImageBBB_01.png.REMOVED.git-id b/src/config-tool/ConfigTool/src/org/hyperion/config/gui/TestImageBBB_01.png.REMOVED.git-id new file mode 100644 index 00000000..ca813483 --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/config/gui/TestImageBBB_01.png.REMOVED.git-id @@ -0,0 +1 @@ +176f5c8e4a406929620764b19e77c5120570325c \ No newline at end of file diff --git a/src/config-tool/ConfigTool/src/org/hyperion/config/gui/TestImageBBB_02.png.REMOVED.git-id b/src/config-tool/ConfigTool/src/org/hyperion/config/gui/TestImageBBB_02.png.REMOVED.git-id new file mode 100644 index 00000000..b3f62ec5 --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/config/gui/TestImageBBB_02.png.REMOVED.git-id @@ -0,0 +1 @@ +048b062d931b7754a533734a1dec21692bce2dc6 \ No newline at end of file diff --git a/src/config-tool/ConfigTool/src/org/hyperion/config/gui/TestImageBBB_03.png.REMOVED.git-id b/src/config-tool/ConfigTool/src/org/hyperion/config/gui/TestImageBBB_03.png.REMOVED.git-id new file mode 100644 index 00000000..5f5afb77 --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/config/gui/TestImageBBB_03.png.REMOVED.git-id @@ -0,0 +1 @@ +bd23dc9ed11283d527effc78e437e8ef18903123 \ No newline at end of file diff --git a/src/config-tool/ConfigTool/src/org/hyperion/config/gui/TestImage_01.png.REMOVED.git-id b/src/config-tool/ConfigTool/src/org/hyperion/config/gui/TestImage_01.png.REMOVED.git-id new file mode 100644 index 00000000..202fe705 --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/config/gui/TestImage_01.png.REMOVED.git-id @@ -0,0 +1 @@ +427d6ffe9935a3011f05b13bcf44a47796e99a80 \ No newline at end of file diff --git a/src/config-tool/ConfigTool/src/org/hyperion/config/gui/TestImage_02.png.REMOVED.git-id b/src/config-tool/ConfigTool/src/org/hyperion/config/gui/TestImage_02.png.REMOVED.git-id new file mode 100644 index 00000000..4d26fccf --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/config/gui/TestImage_02.png.REMOVED.git-id @@ -0,0 +1 @@ +0dd04b5ec932aa251136740c6ea87f71847eb537 \ No newline at end of file diff --git a/src/config-tool/ConfigTool/src/org/hyperion/config/gui/TestImage_03.png.REMOVED.git-id b/src/config-tool/ConfigTool/src/org/hyperion/config/gui/TestImage_03.png.REMOVED.git-id new file mode 100644 index 00000000..bad5b106 --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/config/gui/TestImage_03.png.REMOVED.git-id @@ -0,0 +1 @@ +10fa576b5a494b9e0377e8b944904bfa7ac97cb6 \ No newline at end of file diff --git a/src/config-tool/ConfigTool/src/org/hyperion/config/gui/TestImage_04.png b/src/config-tool/ConfigTool/src/org/hyperion/config/gui/TestImage_04.png new file mode 100644 index 00000000..6106e5fa Binary files /dev/null and b/src/config-tool/ConfigTool/src/org/hyperion/config/gui/TestImage_04.png differ diff --git a/src/config-tool/ConfigTool/src/org/hyperion/config/gui/TestImage_05.png.REMOVED.git-id b/src/config-tool/ConfigTool/src/org/hyperion/config/gui/TestImage_05.png.REMOVED.git-id new file mode 100644 index 00000000..e388ef7e --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/config/gui/TestImage_05.png.REMOVED.git-id @@ -0,0 +1 @@ +620cf4f8a4c8dc62cabe9045c1ad04c38cecb942 \ No newline at end of file diff --git a/src/config-tool/ConfigTool/src/org/hyperion/config/spec/BootSequence.java b/src/config-tool/ConfigTool/src/org/hyperion/config/spec/BootSequence.java new file mode 100644 index 00000000..805eb576 --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/config/spec/BootSequence.java @@ -0,0 +1,29 @@ +package org.hyperion.config.spec; + +public enum BootSequence { + rainbow, + knight_rider, + none; + + public static BootSequence fromString(String pStr) { + for (BootSequence seq : values()) { + if (seq.toString().equalsIgnoreCase(pStr)) { + return seq; + } + } + return none; + } + + @Override + public String toString() { + switch(this) { + case rainbow: + return "Rainbow"; + case knight_rider: + return "Kinght Rider"; + case none: + return "None"; + } + return "None"; + } +} diff --git a/src/config-tool/ConfigTool/src/org/hyperion/config/spec/BorderSide.java b/src/config-tool/ConfigTool/src/org/hyperion/config/spec/BorderSide.java new file mode 100644 index 00000000..a0bd5675 --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/config/spec/BorderSide.java @@ -0,0 +1,22 @@ +package org.hyperion.config.spec; + +public enum BorderSide { + top_left (0.75*Math.PI), + top(0.5*Math.PI), + top_right(0.25*Math.PI), + right(0.0*Math.PI), + bottom_right(-0.25*Math.PI), + bottom(-0.5*Math.PI), + bottom_left(-0.75*Math.PI), + left(1.0*Math.PI); + + private final double mAngle; + + BorderSide(double pAngle) { + mAngle = pAngle; + } + + public double getAngle() { + return mAngle; + } +} diff --git a/src/config-tool/ConfigTool/src/org/hyperion/config/spec/ColorConfig.java b/src/config-tool/ConfigTool/src/org/hyperion/config/spec/ColorConfig.java new file mode 100644 index 00000000..0df65857 --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/config/spec/ColorConfig.java @@ -0,0 +1,77 @@ +package org.hyperion.config.spec; + +import java.util.Locale; + +public class ColorConfig { + + double mSaturationGain = 1.0; + double mValueGain = 1.0; + + double mRedThreshold = 0.0; + double mRedGamma = 1.0; + double mRedBlacklevel = 0.0; + double mRedWhitelevel = 1.0; + + double mGreenThreshold = 0.0; + double mGreenGamma = 1.0; + double mGreenBlacklevel = 0.0; + double mGreenWhitelevel = 1.0; + + double mBlueThreshold = 0.0; + double mBlueGamma = 1.0; + double mBlueBlacklevel = 0.0; + double mBlueWhitelevel = 1.0; + + public String toJsonString() { + StringBuffer strBuf = new StringBuffer(); + strBuf.append("\t\"color\" :\n"); + strBuf.append("\t{\n"); + strBuf.append(hsvToJsonString() + ",\n"); + strBuf.append(rgbToJsonString() + "\n"); + strBuf.append("\t}"); + + return strBuf.toString(); + } + + public String hsvToJsonString() { + StringBuffer strBuf = new StringBuffer(); + strBuf.append("\t\t\"hsv\" :\n"); + strBuf.append("\t\t{\n"); + strBuf.append(String.format(Locale.ROOT, "\t\t\tsaturationGain : %.4f,\n", mSaturationGain)); + strBuf.append(String.format(Locale.ROOT, "\t\t\tsaturationGain : %.4f\n", mValueGain)); + + strBuf.append("\t\t}"); + return strBuf.toString(); + } + + public String rgbToJsonString() { + StringBuffer strBuf = new StringBuffer(); + + strBuf.append("\t\t\"red\" :\n"); + strBuf.append("\t\t{\n"); + strBuf.append(String.format(Locale.ROOT, "\t\t\tthreshold : %.4f,\n", mRedThreshold)); + strBuf.append(String.format(Locale.ROOT, "\t\t\tgamma : %.4f,\n", mRedGamma)); + strBuf.append(String.format(Locale.ROOT, "\t\t\tblacklevel : %.4f,\n", mRedBlacklevel)); + strBuf.append(String.format(Locale.ROOT, "\t\t\twhitelevel : %.4f\n", mRedWhitelevel)); + strBuf.append("\t\t},\n"); + + strBuf.append("\t\t\"green\" :\n"); + strBuf.append("\t\t{\n"); + strBuf.append(String.format(Locale.ROOT, "\t\t\tthreshold : %.4f,\n", mGreenThreshold)); + strBuf.append(String.format(Locale.ROOT, "\t\t\tgamma : %.4f,\n", mGreenGamma)); + strBuf.append(String.format(Locale.ROOT, "\t\t\tblacklevel : %.4f,\n", mGreenBlacklevel)); + strBuf.append(String.format(Locale.ROOT, "\t\t\twhitelevel : %.4f\n", mGreenWhitelevel)); + strBuf.append("\t\t},\n"); + + strBuf.append("\t\t\"blue\" :\n"); + strBuf.append("\t\t{\n"); + strBuf.append(String.format(Locale.ROOT, "\t\t\tthreshold : %.4f,\n", mBlueThreshold)); + strBuf.append(String.format(Locale.ROOT, "\t\t\tgamma : %.4f,\n", mBlueGamma)); + strBuf.append(String.format(Locale.ROOT, "\t\t\tblacklevel : %.4f,\n", mBlueBlacklevel)); + strBuf.append(String.format(Locale.ROOT, "\t\t\twhitelevel : %.4f\n", mBlueWhitelevel)); + strBuf.append("\t\t}"); + + return strBuf.toString(); + } + +} diff --git a/src/config-tool/ConfigTool/src/org/hyperion/config/spec/DeviceConfig.java b/src/config-tool/ConfigTool/src/org/hyperion/config/spec/DeviceConfig.java new file mode 100644 index 00000000..a04e4c17 --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/config/spec/DeviceConfig.java @@ -0,0 +1,25 @@ +package org.hyperion.config.spec; + +public class DeviceConfig { + + String mName = "MyPi"; + DeviceType mType = DeviceType.ws2801; + String mOutput = "/dev/spidev0.0"; + int mBaudrate = 48000; + + public String toJsonString() { + StringBuffer strBuf = new StringBuffer(); + strBuf.append("\t\"device\" :\n"); + strBuf.append("\t{\n"); + + strBuf.append("\t\t\"name\" : \"").append(mName).append("\",\n"); + strBuf.append("\t\t\"type\" : \"").append(mType).append("\",\n"); + strBuf.append("\t\t\"output\" : \"").append(mOutput).append("\",\n"); + strBuf.append("\t\t\"rate\" : ").append(mBaudrate).append("\n"); + + strBuf.append("\t}"); + + return strBuf.toString(); + } + +} diff --git a/src/config-tool/ConfigTool/src/org/hyperion/config/spec/DeviceType.java b/src/config-tool/ConfigTool/src/org/hyperion/config/spec/DeviceType.java new file mode 100644 index 00000000..f3cfa8ee --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/config/spec/DeviceType.java @@ -0,0 +1,9 @@ +package org.hyperion.config.spec; + +public enum DeviceType { + ws2801, + test, + none; + + +} diff --git a/src/config-tool/ConfigTool/src/org/hyperion/config/spec/Led.java b/src/config-tool/ConfigTool/src/org/hyperion/config/spec/Led.java new file mode 100644 index 00000000..8135b3fc --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/config/spec/Led.java @@ -0,0 +1,21 @@ +package org.hyperion.config.spec; + +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + + +public class Led { + + public int mLedSeqNr; + + public BorderSide mSide; + + public Point2D mLocation; + + public Rectangle2D mImageRectangle; + + @Override + public String toString() { + return "Led[" + mLedSeqNr + "] Location=" + mLocation + " Rectangle=" + mImageRectangle; + } +} diff --git a/src/config-tool/ConfigTool/src/org/hyperion/config/spec/LedFrameConstruction.java b/src/config-tool/ConfigTool/src/org/hyperion/config/spec/LedFrameConstruction.java new file mode 100644 index 00000000..8adc320c --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/config/spec/LedFrameConstruction.java @@ -0,0 +1,69 @@ +package org.hyperion.config.spec; + +import java.util.Observable; + + + +/** + * The LedFrame describes the construction of leds along the sides of the TV screen. + * + */ +public class LedFrameConstruction extends Observable { + + public enum Direction { + clockwise, + counter_clockwise; + } + + /** True if the leds are organised clockwise else false (counter clockwise) */ + public boolean clockwiseDirection; + + /** True if the top left corner has a led else false */ + public boolean topLeftCorner; + /** True if the top right corner has a led else false */ + public boolean topRightCorner; + /** True if the bottom left corner has a led else false */ + public boolean bottomLeftCorner; + /** True if the bottom right corner has a led else false */ + public boolean bottomRightCorner; + + /** The number of leds between the top-left corner and the top-right corner of the screen + (excluding the corner leds) */ + public int topLedCnt; + /** The number of leds between the bottom-left corner and the bottom-right corner of the screen + (excluding the corner leds) */ + public int bottomLedCnt; + + /** The number of leds between the top-left corner and the bottom-left corner of the screen + (excluding the corner leds) */ + public int leftLedCnt; + /** The number of leds between the top-right corner and the bottom-right corner of the screen + (excluding the corner leds) */ + public int rightLedCnt; + + /** The offset (in leds) of the starting led counted clockwise from the top-left corner */ + public int firstLedOffset; + + /** The 'integration depth' of the leds along the horizontal axis of the tv */ + public double horizontalDepth = 0.05; + /** The 'integration depth' of the leds along the vertical axis of the tv */ + public double verticalDepth = 0.05; + + /** The fraction of overlap from one to another led */ + public double overlapFraction = 0.0; + + public int getLedCount() { + int cornerLedCnt = 0; + if (topLeftCorner) ++cornerLedCnt; + if (topRightCorner) ++cornerLedCnt; + if (bottomLeftCorner) ++cornerLedCnt; + if (bottomRightCorner) ++cornerLedCnt; + + return topLedCnt + bottomLedCnt + leftLedCnt + rightLedCnt + cornerLedCnt; + } + + @Override + public void setChanged() { + super.setChanged(); + } +} diff --git a/src/config-tool/ConfigTool/src/org/hyperion/config/spec/MiscConfig.java b/src/config-tool/ConfigTool/src/org/hyperion/config/spec/MiscConfig.java new file mode 100644 index 00000000..82e43e78 --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/config/spec/MiscConfig.java @@ -0,0 +1,46 @@ +package org.hyperion.config.spec; + +import java.util.Locale; + + +public class MiscConfig { + BootSequence mBootSequence = BootSequence.rainbow; + int mBootSequenceLength_ms = 3000; + + boolean mBlackborderDetector = true; + + int mFrameGrabberWidth = 64; + int mFrameGrabberHeight = 64; + int mFrameGrabberInterval_ms = 100; + + boolean mXbmcChecker = true; + String mXbmcAddress = "127.0.0.1"; + int mXbmcTcpPort = 9090; + + public String toJsonString() { + StringBuffer strBuf = new StringBuffer(); + strBuf.append("\t\"bootsequence\" :\n"); + strBuf.append("\t{\n"); + strBuf.append(String.format(Locale.ROOT, "\t\t\"type\" : \"%s\",\n", mBootSequence)); + strBuf.append(String.format(Locale.ROOT, "\t\t\"duration_ms\" : %d\n", mBootSequenceLength_ms)); + strBuf.append("\t},\n"); + + strBuf.append("\t\"framegrabber\" :\n"); + strBuf.append("\t{\n"); + strBuf.append(String.format(Locale.ROOT, "\t\t\"width\" : %d,\n", mFrameGrabberWidth)); + strBuf.append(String.format(Locale.ROOT, "\t\t\"height\" : %d,\n", mFrameGrabberHeight)); + strBuf.append(String.format(Locale.ROOT, "\t\t\"frequency_Hz\" : %.1f\n", 1000.0/mFrameGrabberInterval_ms)); + strBuf.append("\t},\n"); + + strBuf.append("\t\"xbmcVideoChecker\" :\n"); + strBuf.append("\t{\n"); + strBuf.append(String.format(Locale.ROOT, "\t\t\"enable\" : %s,\n", mXbmcChecker)); + strBuf.append(String.format(Locale.ROOT, "\t\t\"xbmcAddress\" : \"%s\",\n", mXbmcAddress)); + strBuf.append(String.format(Locale.ROOT, "\t\t\"xbmcTcpPort\" : %d\n", mXbmcTcpPort)); + strBuf.append("\t}"); + + return strBuf.toString(); + } + + +} diff --git a/src/config-tool/ConfigTool/src/org/hyperion/config/spec/Ws2801Led.java b/src/config-tool/ConfigTool/src/org/hyperion/config/spec/Ws2801Led.java new file mode 100644 index 00000000..ec46f0d6 --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/config/spec/Ws2801Led.java @@ -0,0 +1,83 @@ +package org.hyperion.config.spec; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; + +import javax.swing.JComponent; + +public class Ws2801Led extends JComponent { + + enum Border { + top, + topleft, + left, + bottomleft, + bottom, + bottomright, + right, + topright; + } + + final int size = 12; + final int halfSize = size/2; + + final Border mBorder; + + public Ws2801Led(Border pBorder) { + mBorder = pBorder; + } + + + @Override + protected void paintComponent(Graphics g) { + Graphics2D g2d = (Graphics2D) g.create(); + +// g2d.setColor(Color.BLACK); +// g2d.drawRect(0, 0, getWidth()-1, getHeight()-1); + + switch (mBorder) { + case top: + g2d.translate(getWidth()/2, getHeight()); + break; + case topleft: + g2d.translate(getWidth(), getHeight()); + g2d.rotate(1.75*Math.PI); + break; + case left: + g2d.translate(0, getHeight()/2); + g2d.rotate(Math.PI*0.5); + break; + case bottomleft: + g2d.translate(getWidth(), 0); + g2d.rotate(-0.75*Math.PI); + break; + case bottom: + g2d.translate(getWidth()/2, 0); + g2d.rotate(Math.PI*1.0); + break; + case bottomright: + g2d.rotate(0.75*Math.PI); + break; + case right: + g2d.translate(getWidth(), getHeight()/2); + g2d.rotate(Math.PI*1.5); + break; + case topright: + g2d.translate(0, getHeight()); + g2d.rotate(0.25*Math.PI); + break; + } + + g2d.setColor(new Color(255, 0, 0, 172)); + g2d.fillRoundRect(-3, -12, 6, 6, 2, 2); + + g2d.setColor(new Color(255, 0, 0, 255)); + g2d.drawRoundRect(-3, -12, 6, 6, 2, 2); + + g2d.setColor(Color.GRAY); + g2d.drawRect(-halfSize, -halfSize, size, halfSize); + g2d.fillRect(-halfSize, -halfSize, size, halfSize); + + } +}