Commit d175ba5513176028c75d5a51711a9394e811a89b
1 parent
bd56dbdb
VRGNYMusicLight application java presque finie
Showing
32 changed files
with
791 additions
and
92 deletions
Show diff stats
VRGNYMusicLights/Sources/AnimationPlayer.java renamed to VRGNYMusicLights/Sources/ApplicationJava/AnimationPlayer.java
VRGNYMusicLights/Sources/ApplicationJava/CommandJPanel.java
0 → 100644
... | ... | @@ -0,0 +1,95 @@ |
1 | +import java.awt.Color; | |
2 | +import java.awt.Font; | |
3 | +import java.awt.event.ActionEvent; | |
4 | +import java.awt.event.ActionListener; | |
5 | + | |
6 | +import javax.swing.BorderFactory; | |
7 | +import javax.swing.BoxLayout; | |
8 | +import javax.swing.JButton; | |
9 | +import javax.swing.JLabel; | |
10 | +import javax.swing.JPanel; | |
11 | + | |
12 | +public class CommandJPanel extends JPanel implements ActionListener { | |
13 | + private static final long serialVersionUID = 1L; | |
14 | + private static final Font titleFont = new Font(new JLabel().getFont().getName(), Font.BOLD, 14); | |
15 | + | |
16 | + private JButton addPattern; | |
17 | + private JButton editPattern; | |
18 | + private JButton removePattern; | |
19 | + private JButton exports; | |
20 | + private JButton imports; | |
21 | + | |
22 | + private Interface interf; | |
23 | + | |
24 | + public CommandJPanel(Interface interf) { | |
25 | + this.interf = interf; | |
26 | + setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); | |
27 | + setBorder(BorderFactory.createMatteBorder(0, 4, 0, 0, Color.LIGHT_GRAY)); | |
28 | + | |
29 | + // Title | |
30 | + | |
31 | + JLabel title = new JLabel("Commands :"); | |
32 | + title.setFont(titleFont); | |
33 | + add(title); | |
34 | + | |
35 | + // Buttons | |
36 | + | |
37 | + addPattern = new JButton("Add pattern"); | |
38 | + editPattern = new JButton("Edit pattern"); | |
39 | + removePattern = new JButton("Remove pattern"); | |
40 | + exports = new JButton("Export"); | |
41 | + imports = new JButton("Import"); | |
42 | + | |
43 | + addPattern.setMaximumSize(removePattern.getMaximumSize()); | |
44 | + editPattern.setMaximumSize(removePattern.getMaximumSize()); | |
45 | + exports.setMaximumSize(removePattern.getMaximumSize()); | |
46 | + imports.setMaximumSize(removePattern.getMaximumSize()); | |
47 | + | |
48 | + addPattern.addActionListener(this); | |
49 | + editPattern.addActionListener(this); | |
50 | + removePattern.addActionListener(this); | |
51 | + exports.addActionListener(this); | |
52 | + imports.addActionListener(this); | |
53 | + | |
54 | + add(addPattern); | |
55 | + add(editPattern); | |
56 | + add(removePattern); | |
57 | + add(exports); | |
58 | + add(imports); | |
59 | + } | |
60 | + | |
61 | + @Override | |
62 | + public void actionPerformed(ActionEvent e) { | |
63 | + if(e.getSource() == addPattern) { | |
64 | + PatternEditorJDialog dialog = new PatternEditorJDialog(interf); | |
65 | + Music music = dialog.showDialog(); | |
66 | + if(music == null) | |
67 | + return; | |
68 | + interf.musicList.addMusic(music); | |
69 | + interf.timeLinePanel.updateList(); | |
70 | + } else if(e.getSource() == editPattern) { | |
71 | + int index = interf.timeLineList.getSelectedIndex(); | |
72 | + if(index == -1) | |
73 | + return; | |
74 | + PatternEditorJDialog dialog = new PatternEditorJDialog(interf, interf.musicList.getList().get(index)); | |
75 | + Music music = dialog.showDialog(); | |
76 | + if(music == null) | |
77 | + return; | |
78 | + interf.musicList.setMusicAt(index, music); | |
79 | + interf.timeLinePanel.updateList(); | |
80 | + } else if(e.getSource() == removePattern) { | |
81 | + int index = interf.timeLineList.getSelectedIndex(); | |
82 | + if(index == -1) | |
83 | + return; | |
84 | + interf.musicList.deleteMusic(index); | |
85 | + interf.timeLinePanel.updateList(); | |
86 | + } else if(e.getSource() == exports) { | |
87 | + ImportExport.exportWithDialog(interf.musicList); | |
88 | + } else if(e.getSource() == imports) { | |
89 | + MusicList newActionList = ImportExport.importsWithDialog(); | |
90 | + if(newActionList != null) | |
91 | + interf.musicList = newActionList; | |
92 | + interf.timeLinePanel.updateList(); | |
93 | + } | |
94 | + } | |
95 | +} | ... | ... |
VRGNYMusicLights/Sources/ApplicationJava/CustomSliderUI.java
0 → 100644
... | ... | @@ -0,0 +1,151 @@ |
1 | +import java.awt.BasicStroke; | |
2 | +import java.awt.Color; | |
3 | +import java.awt.Dimension; | |
4 | +import java.awt.Graphics; | |
5 | +import java.awt.Graphics2D; | |
6 | +import java.awt.Rectangle; | |
7 | +import java.awt.RenderingHints; | |
8 | +import java.awt.Shape; | |
9 | +import java.awt.Stroke; | |
10 | +import java.awt.geom.Ellipse2D; | |
11 | + | |
12 | +import javax.swing.JComponent; | |
13 | +import javax.swing.JSlider; | |
14 | +import javax.swing.SwingConstants; | |
15 | +import javax.swing.plaf.ComponentUI; | |
16 | +import javax.swing.plaf.basic.BasicSliderUI; | |
17 | + | |
18 | +public class CustomSliderUI extends BasicSliderUI { | |
19 | + private final BasicStroke stroke = new BasicStroke(2f); | |
20 | + private JSlider slider; | |
21 | + | |
22 | + public CustomSliderUI(JSlider b) { | |
23 | + super(b); | |
24 | + this.slider = b; | |
25 | + } | |
26 | + | |
27 | + public static ComponentUI createUI(JComponent c) { | |
28 | + return new CustomSliderUI((JSlider)c); | |
29 | + } | |
30 | + | |
31 | + | |
32 | + @Override | |
33 | + protected void calculateThumbSize() { | |
34 | + super.calculateThumbSize(); | |
35 | + thumbRect.setSize(thumbRect.width, thumbRect.height); | |
36 | + } | |
37 | + | |
38 | + /** Creates a listener to handle track events in the specified slider.*/ | |
39 | + @Override | |
40 | + protected TrackListener createTrackListener(JSlider slider) { | |
41 | + return new TrackListener(); | |
42 | + } | |
43 | + | |
44 | + | |
45 | + @Override | |
46 | + protected void calculateThumbLocation() { | |
47 | + // Call superclass method for lower thumb location. | |
48 | + super.calculateThumbLocation(); | |
49 | + | |
50 | + // Adjust upper value to snap to ticks if necessary. | |
51 | + if (slider.getSnapToTicks()) { | |
52 | + int upperValue = slider.getValue() + slider.getExtent(); | |
53 | + int snappedValue = upperValue; | |
54 | + int majorTickSpacing = slider.getMajorTickSpacing(); | |
55 | + int minorTickSpacing = slider.getMinorTickSpacing(); | |
56 | + int tickSpacing = 0; | |
57 | + | |
58 | + if (minorTickSpacing > 0) { | |
59 | + tickSpacing = minorTickSpacing; | |
60 | + } else if (majorTickSpacing > 0) { | |
61 | + tickSpacing = majorTickSpacing; | |
62 | + } | |
63 | + | |
64 | + if (tickSpacing != 0) { | |
65 | + // If it's not on a tick, change the value | |
66 | + if ((upperValue - slider.getMinimum()) % tickSpacing != 0) { | |
67 | + float temp = (float)(upperValue - slider.getMinimum()) / (float)tickSpacing; | |
68 | + int whichTick = Math.round(temp); | |
69 | + snappedValue = slider.getMinimum() + (whichTick * tickSpacing); | |
70 | + } | |
71 | + | |
72 | + if (snappedValue != upperValue) { | |
73 | + slider.setExtent(snappedValue - slider.getValue()); | |
74 | + } | |
75 | + } | |
76 | + } | |
77 | + | |
78 | + // Calculate upper thumb location. The thumb is centered over its | |
79 | + // value on the track. | |
80 | + if (slider.getOrientation() == JSlider.HORIZONTAL) { | |
81 | + int upperPosition = xPositionForValue(slider.getValue() + slider.getExtent()); | |
82 | + thumbRect.x = upperPosition - (thumbRect.width / 2); | |
83 | + thumbRect.y = trackRect.y; | |
84 | + | |
85 | + } else { | |
86 | + int upperPosition = yPositionForValue(slider.getValue() + slider.getExtent()); | |
87 | + thumbRect.x = trackRect.x; | |
88 | + thumbRect.y = upperPosition - (thumbRect.height / 2); | |
89 | + } | |
90 | + slider.repaint(); | |
91 | + } | |
92 | + | |
93 | + /** Returns the size of a thumb. | |
94 | + * Parent method not use size from LaF | |
95 | + * @return size of trumb */ | |
96 | + @Override | |
97 | + protected Dimension getThumbSize() { | |
98 | + return new Dimension(5, 10); | |
99 | + } | |
100 | + | |
101 | + | |
102 | + private Shape createThumbShape(int width, int height) { | |
103 | + Ellipse2D shape = new Ellipse2D.Double(0, 0, width, height); | |
104 | + return shape; | |
105 | + } | |
106 | + | |
107 | + @Override | |
108 | + public void paintTrack(Graphics g) { | |
109 | + Graphics2D g2d = (Graphics2D) g; | |
110 | + Stroke old = g2d.getStroke(); | |
111 | + g2d.setStroke(stroke); | |
112 | + g2d.setPaint(slider.isEnabled() ? Color.LIGHT_GRAY : Color.WHITE); | |
113 | + Color oldColor = slider.isEnabled() ? Color.LIGHT_GRAY : Color.WHITE; | |
114 | + Rectangle trackBounds = trackRect; | |
115 | + if (slider.getOrientation() == SwingConstants.HORIZONTAL) { | |
116 | + g2d.drawLine(trackRect.x, trackRect.y + trackRect.height / 2, | |
117 | + trackRect.x + trackRect.width, trackRect.y + trackRect.height / 2); | |
118 | + int lowerX = thumbRect.width / 2; | |
119 | + int upperX = thumbRect.x + (thumbRect.width / 2); | |
120 | + int cy = (trackBounds.height / 2) - 2; | |
121 | + g2d.translate(trackBounds.x, trackBounds.y + cy); | |
122 | + g2d.setColor(slider.isEnabled() ? Color.BLACK : Color.LIGHT_GRAY); | |
123 | + g2d.drawLine(lowerX - trackBounds.x, 2, upperX - trackBounds.x, 2); | |
124 | + g2d.translate(-trackBounds.x, -(trackBounds.y + cy)); | |
125 | + g2d.setColor(oldColor); | |
126 | + } | |
127 | + g2d.setStroke(old); | |
128 | + } | |
129 | + | |
130 | + | |
131 | + | |
132 | + /** Overrides superclass method to do nothing. Thumb painting is handled | |
133 | + * within the <code>paint()</code> method.*/ | |
134 | + @Override | |
135 | + public void paintThumb(Graphics g) { | |
136 | + Rectangle knobBounds = thumbRect; | |
137 | + int w = knobBounds.width; | |
138 | + int h = knobBounds.height; | |
139 | + Graphics2D g2d = (Graphics2D) g.create(); | |
140 | + Shape thumbShape = createThumbShape(w - 1, h - 1); | |
141 | + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, | |
142 | + RenderingHints.VALUE_ANTIALIAS_ON); | |
143 | + g2d.translate(knobBounds.x, knobBounds.y); | |
144 | + g2d.setColor(slider.isEnabled() ? Color.LIGHT_GRAY : Color.WHITE); | |
145 | + g2d.fill(thumbShape); | |
146 | + | |
147 | + g2d.setColor(slider.isEnabled() ? Color.BLACK : Color.LIGHT_GRAY); | |
148 | + g2d.draw(thumbShape); | |
149 | + g2d.dispose(); | |
150 | + } | |
151 | +} | |
0 | 152 | \ No newline at end of file | ... | ... |
VRGNYMusicLights/Sources/ApplicationJava/ImportExport.java
0 → 100644
... | ... | @@ -0,0 +1,73 @@ |
1 | +import java.io.BufferedWriter; | |
2 | +import java.io.File; | |
3 | +import java.io.FileWriter; | |
4 | +import java.io.IOException; | |
5 | +import java.nio.charset.Charset; | |
6 | +import java.nio.file.Files; | |
7 | +import java.nio.file.Paths; | |
8 | + | |
9 | +import javax.swing.JFileChooser; | |
10 | +import javax.swing.JOptionPane; | |
11 | +import javax.swing.filechooser.FileNameExtensionFilter; | |
12 | + | |
13 | +public class ImportExport { | |
14 | + public static void exportWithDialog(MusicList list) { | |
15 | + JFileChooser chooser = new JFileChooser(); | |
16 | + FileNameExtensionFilter filter = new FileNameExtensionFilter("Array data", "adata"); | |
17 | + chooser.setFileFilter(filter); | |
18 | + chooser.setApproveButtonText("Exporter"); | |
19 | + int returnVal = chooser.showOpenDialog(null); | |
20 | + if(returnVal == JFileChooser.APPROVE_OPTION) | |
21 | + export(list, chooser.getSelectedFile().getPath()); | |
22 | + } | |
23 | + private static void export(MusicList list, String path) { | |
24 | + String str = "";//list.getLeftDeltaArray() + "\n" + list.getRightDeltaArray() + "\n" + list.getLeftDelaiArray() + "\n" + list.getRightDelaiArray(); | |
25 | + | |
26 | + if(!path.endsWith(".adata")) | |
27 | + path += ".adata"; | |
28 | + BufferedWriter bufferedWriter = null; | |
29 | + try { | |
30 | + File file = new File(path); | |
31 | + if (!file.exists()) | |
32 | + file.createNewFile(); | |
33 | + bufferedWriter = new BufferedWriter(new FileWriter(file)); | |
34 | + bufferedWriter.write(str); | |
35 | + bufferedWriter.close(); | |
36 | + } catch (IOException e) { | |
37 | + e.printStackTrace(); | |
38 | + } | |
39 | + } | |
40 | + | |
41 | + public static MusicList importsWithDialog() { | |
42 | + JFileChooser chooser = new JFileChooser(); | |
43 | + FileNameExtensionFilter filter = new FileNameExtensionFilter("Array data", "adata"); | |
44 | + chooser.setFileFilter(filter); | |
45 | + chooser.setMultiSelectionEnabled(false); | |
46 | + chooser.setApproveButtonText("Importer"); | |
47 | + int returnVal = chooser.showOpenDialog(null); | |
48 | + if(returnVal == JFileChooser.APPROVE_OPTION && chooser.getSelectedFile().exists() && chooser.getSelectedFile().isFile()) | |
49 | + return imports(chooser.getSelectedFile().getPath()); | |
50 | + if(returnVal == JFileChooser.APPROVE_OPTION) | |
51 | + JOptionPane.showMessageDialog(null, "You have to choose an exisiting file", "Import error", JOptionPane.ERROR_MESSAGE); | |
52 | + return null; | |
53 | + } | |
54 | + private static MusicList imports(String path) { | |
55 | + try { | |
56 | + byte[] encoded = Files.readAllBytes(Paths.get(path)); | |
57 | + String str = new String(encoded, Charset.defaultCharset()); | |
58 | + | |
59 | + //long[][] longList = Util.getArraysFromImport(str); | |
60 | + /*if(longList == null) { | |
61 | + JOptionPane.showMessageDialog(null, "The choosen file is invalid or currupted", "Import error", JOptionPane.ERROR_MESSAGE); | |
62 | + return null; | |
63 | + } | |
64 | + int[][] intList = new int[2][longList[0].length]; | |
65 | + for(int i=0; i<2; i++) | |
66 | + for(int j=0; j<longList[0].length; j++) | |
67 | + intList[i][j] = (int) longList[i][j]; | |
68 | + | |
69 | + return new MusicList(intList[0], intList[1], longList[2], longList[3]);*/ | |
70 | + } catch (IOException ignored) {} | |
71 | + return null; | |
72 | + } | |
73 | +} | ... | ... |
VRGNYMusicLights/Sources/Interface.java renamed to VRGNYMusicLights/Sources/ApplicationJava/Interface.java
1 | 1 | import java.awt.BorderLayout; |
2 | +import java.awt.Dimension; | |
2 | 3 | import java.awt.event.WindowAdapter; |
3 | 4 | import java.awt.event.WindowEvent; |
4 | 5 | |
5 | 6 | import javax.swing.JFrame; |
6 | 7 | import javax.swing.JPanel; |
8 | +import javax.swing.JSlider; | |
7 | 9 | |
8 | 10 | public class Interface extends JFrame{ |
9 | 11 | private static final long serialVersionUID = 1L; |
... | ... | @@ -15,14 +17,16 @@ public class Interface extends JFrame{ |
15 | 17 | protected TimeLineJPanel timeLinePanel; |
16 | 18 | protected TimeLineJList timeLineList; |
17 | 19 | protected LightCanvasJPanel lightCanvas; |
20 | + protected JSlider timeSlider; | |
18 | 21 | protected long tick = 0; |
19 | 22 | |
20 | 23 | public Interface(MusicList musicList, final Runnable executeOnClose) { |
21 | 24 | super("VRGNYMusicLights"); |
22 | 25 | this.musicList = musicList; |
23 | - setResizable(false); | |
24 | 26 | populateWindow(); |
25 | 27 | pack(); |
28 | + setMinimumSize(new Dimension(600, 500)); | |
29 | + setSize(new Dimension(800, 600)); | |
26 | 30 | setLocationRelativeTo(null); // center window |
27 | 31 | getContentPane().requestFocus(); |
28 | 32 | |
... | ... | @@ -39,6 +43,7 @@ public class Interface extends JFrame{ |
39 | 43 | } |
40 | 44 | |
41 | 45 | protected void computeTick() { |
46 | + timeSlider.setValue((int) tick); | |
42 | 47 | lightCanvas.paintLights(musicList.render(tick)); |
43 | 48 | timeLineList.repaint(); |
44 | 49 | timeLinePanel.updateTick(); |
... | ... | @@ -46,10 +51,11 @@ public class Interface extends JFrame{ |
46 | 51 | |
47 | 52 | private void populateWindow() { |
48 | 53 | JPanel mainPanel = new JPanel(new BorderLayout()); |
49 | - timeLinePanel = new TimeLineJPanel(this, musicList); | |
54 | + timeLinePanel = new TimeLineJPanel(this); | |
50 | 55 | mainPanel.add(timeLinePanel, BorderLayout.CENTER); |
51 | 56 | lightCanvas = new LightCanvasJPanel(); |
52 | 57 | mainPanel.add(new PlayJPanel(this, lightCanvas), BorderLayout.SOUTH); |
58 | + mainPanel.add(new CommandJPanel(this), BorderLayout.EAST); | |
53 | 59 | add(mainPanel); |
54 | 60 | } |
55 | 61 | } | ... | ... |
VRGNYMusicLights/Sources/InvalidPatternException.java renamed to VRGNYMusicLights/Sources/ApplicationJava/InvalidPatternException.java
VRGNYMusicLights/Sources/LightCanvasJPanel.java renamed to VRGNYMusicLights/Sources/ApplicationJava/LightCanvasJPanel.java
VRGNYMusicLights/Sources/Main.java renamed to VRGNYMusicLights/Sources/ApplicationJava/Main.java
... | ... | @@ -3,6 +3,10 @@ import javax.swing.JOptionPane; |
3 | 3 | /* TODO list : |
4 | 4 | * - keyboard listener for animation player (play / pause = space, forward = semicolon, backward = comma, stop = backspace) |
5 | 5 | * - pattern timeline info to follow scroll horizontal ? |
6 | + * - export / import | |
7 | + * - play on arduino button | |
8 | + * - slider update on edit / add / delete music | |
9 | + * - checkbox option to follow the tick mark when playing | |
6 | 10 | */ |
7 | 11 | public class Main { |
8 | 12 | public static void main(String[] args) throws InterruptedException { |
... | ... | @@ -21,16 +25,16 @@ public class Main { |
21 | 25 | Thread.sleep(1000);*/ |
22 | 26 | |
23 | 27 | MusicList musicList = new MusicList(null); |
24 | - musicList.addMusic( | |
28 | + /*musicList.addMusic( | |
25 | 29 | new Music( |
26 | - new MusicPattern(new int[] {0, 10, 100, 10, 100}, 100, 1000), | |
27 | - new MusicPath(MusicPath.CENTER_OUT, 1000), | |
30 | + new MusicPattern(new int[] {0, 10, 100, 10, 100}, 10, 1000), | |
31 | + new MusicPath(MusicPath.CENTER_IN, 1000), | |
28 | 32 | 1)); |
29 | 33 | musicList.addMusic( |
30 | 34 | new Music( |
31 | 35 | new MusicPattern(new int[] {0, 10, 100, 10, 100}, 1, 0), |
32 | 36 | new MusicPath(MusicPath.CENTER_OUT, 1000), |
33 | - 1)); | |
37 | + 1));*/ | |
34 | 38 | |
35 | 39 | Interface i = new Interface(musicList, new Runnable() { |
36 | 40 | @Override | ... | ... |
VRGNYMusicLights/Sources/MalformedCoordinates.java renamed to VRGNYMusicLights/Sources/ApplicationJava/MalformedCoordinates.java
VRGNYMusicLights/Sources/Music.java renamed to VRGNYMusicLights/Sources/ApplicationJava/Music.java
1 | 1 | |
2 | 2 | public class Music { |
3 | 3 | private MusicPattern pattern; |
4 | + public MusicPath path; | |
4 | 5 | private int[] lightTickDelais; |
5 | 6 | private double volume; |
6 | 7 | |
7 | 8 | public Music(MusicPattern pattern, MusicPath path, double volume) { |
8 | 9 | this.pattern = pattern; |
10 | + this.path = path; | |
9 | 11 | this.lightTickDelais = path.calculateTickDelais(); |
10 | 12 | this.volume = volume; |
11 | 13 | } |
12 | - | |
14 | + | |
13 | 15 | public MusicPattern getMusicPattern() { return pattern; } |
16 | + public MusicPath getMusicPath() { return path; } | |
17 | + public double getVolume() { return volume; } | |
14 | 18 | |
15 | 19 | public double[] render(long tick) { |
16 | 20 | double[] lights = new double[lightTickDelais.length]; | ... | ... |
VRGNYMusicLights/Sources/MusicList.java renamed to VRGNYMusicLights/Sources/ApplicationJava/MusicList.java
... | ... | @@ -11,6 +11,7 @@ public class MusicList { |
11 | 11 | |
12 | 12 | public ArrayList<Music> getList() { return musics; } |
13 | 13 | public void addMusic(Music music) { musics.add(music); } |
14 | + public void setMusicAt(int index, Music music) { musics.set(index, music); } | |
14 | 15 | public void deleteMusic(int index) { musics.remove(index); } |
15 | 16 | |
16 | 17 | public double[] render(long tick) { | ... | ... |
VRGNYMusicLights/Sources/MusicPath.java renamed to VRGNYMusicLights/Sources/ApplicationJava/MusicPath.java
... | ... | @@ -36,6 +36,19 @@ public class MusicPath { |
36 | 36 | {1, 0.83}, {1, 0.885}, {1, 0.94} //M6l1 |
37 | 37 | }; |
38 | 38 | |
39 | + public static final String[] pathNames = new String[] { | |
40 | + "Vertical down", | |
41 | + "Vertical up", | |
42 | + "Horizontal right to left", | |
43 | + "Horizontal left to right", | |
44 | + "Diagonal up right to down left", | |
45 | + "Diagonal down left to up right", | |
46 | + "Diagonal up left to down right", | |
47 | + "Diagonal down right to up left", | |
48 | + "Center out", | |
49 | + "Center in", | |
50 | + "Flashing", | |
51 | + }; | |
39 | 52 | public static final int VERTICAL_DOWN = 0; |
40 | 53 | public static final int VERTICAL_UP = 1; |
41 | 54 | public static final int HORIZONTAL_TO_LEFT = 2; |
... | ... | @@ -58,6 +71,9 @@ public class MusicPath { |
58 | 71 | this.effectDuration = effectDuration; |
59 | 72 | this.lightsCoords = lightsCoords; |
60 | 73 | } |
74 | + | |
75 | + public int getAnimation() { return animation; } | |
76 | + public int getEffectDuration() { return effectDuration; } | |
61 | 77 | |
62 | 78 | public int[] calculateTickDelais() { // tick in ms |
63 | 79 | int[] ticksDelais = new int[lightsCoords.length]; | ... | ... |
VRGNYMusicLights/Sources/MusicPattern.java renamed to VRGNYMusicLights/Sources/ApplicationJava/MusicPattern.java
... | ... | @@ -23,10 +23,11 @@ public class MusicPattern { |
23 | 23 | for(int i=1; i<5; i++) |
24 | 24 | this.patternTiming[i] = this.patternTiming[i-1] + pattern[i]; |
25 | 25 | this.begin = begin; |
26 | - this.stop = repeat * totalLength; | |
26 | + this.stop = repeat * totalLength + begin; | |
27 | 27 | this.repeat = repeat; |
28 | 28 | } |
29 | 29 | |
30 | + public int[] getPattern() { return pattern; } | |
30 | 31 | public int[] getPatternTiming() { return patternTiming; } |
31 | 32 | public long getStop() { return stop; } |
32 | 33 | public long getBegin() { return begin; } | ... | ... |
VRGNYMusicLights/Sources/MusicRenderer.java renamed to VRGNYMusicLights/Sources/ApplicationJava/MusicRenderer.java
1 | 1 | import java.awt.Color; |
2 | 2 | import java.awt.Component; |
3 | +import java.awt.Dimension; | |
4 | +import java.awt.Font; | |
3 | 5 | import java.util.ArrayList; |
4 | 6 | |
5 | 7 | import javax.swing.Box; |
... | ... | @@ -12,8 +14,10 @@ import javax.swing.ListCellRenderer; |
12 | 14 | public class MusicRenderer extends JPanel implements ListCellRenderer<Music> { |
13 | 15 | private static final long serialVersionUID = 1L; |
14 | 16 | private static final Color DEFAULT_BACKGROUND = new JPanel().getBackground(); |
17 | + private static final Font defaultFont = new Font(new JLabel().getFont().getName(), Font.PLAIN, new JLabel().getFont().getSize()); | |
15 | 18 | |
16 | 19 | private TimeLineJPanel timeLine; |
20 | + private int infoPadding = 0; | |
17 | 21 | |
18 | 22 | public ArrayList<PatternJPanel> patterns; |
19 | 23 | |
... | ... | @@ -22,24 +26,34 @@ public class MusicRenderer extends JPanel implements ListCellRenderer<Music> { |
22 | 26 | this.patterns = new ArrayList<>(); |
23 | 27 | } |
24 | 28 | |
29 | + public void setInfoPadding(int infoPadding) { this.infoPadding = infoPadding; } | |
30 | + | |
25 | 31 | @Override |
26 | 32 | public Component getListCellRendererComponent(JList<? extends Music> list, Music music, int index, |
27 | 33 | boolean isSelected, boolean cellHasFocus) { |
28 | 34 | removeAll(); |
29 | - | |
30 | - if(isSelected) { | |
31 | - setBackground(Color.LIGHT_GRAY); | |
32 | - } else { | |
33 | - setBackground(DEFAULT_BACKGROUND); | |
34 | - } | |
35 | + if(music == null) | |
36 | + return this; | |
35 | 37 | |
36 | 38 | setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); |
37 | 39 | |
38 | 40 | JPanel infoPanel = new JPanel(); |
39 | 41 | infoPanel.setLayout(new BoxLayout(infoPanel, BoxLayout.LINE_AXIS)); |
40 | - infoPanel.add(new JLabel("Pattern " + String.valueOf(index) + " :")); | |
41 | - //TODO rigid area to follow scroll ? | |
42 | + infoPanel.add(Box.createRigidArea(new Dimension(infoPadding, 0))); | |
43 | + JLabel infoLabel = new JLabel("Pattern " + String.valueOf(index) + " : " | |
44 | + + "(vol : " + String.valueOf(music.getVolume()) + ", " | |
45 | + + "effect : " + MusicPath.pathNames[music.getMusicPath().getAnimation()] + ", " | |
46 | + + "effect duration : " + Util.tickToText(music.getMusicPath().getEffectDuration()) + ")"); | |
47 | + infoLabel.setFont(defaultFont); | |
48 | + infoPanel.add(infoLabel); | |
42 | 49 | infoPanel.add(Box.createHorizontalGlue()); |
50 | + | |
51 | + if(isSelected) { | |
52 | + infoPanel.setBackground(Color.LIGHT_GRAY); | |
53 | + } else { | |
54 | + infoPanel.setBackground(DEFAULT_BACKGROUND); | |
55 | + } | |
56 | + | |
43 | 57 | add(infoPanel); |
44 | 58 | |
45 | 59 | PatternJPanel pattern = new PatternJPanel(music, timeLine); | ... | ... |
VRGNYMusicLights/Sources/NoSerialPortException.java renamed to VRGNYMusicLights/Sources/ApplicationJava/NoSerialPortException.java
VRGNYMusicLights/Sources/ApplicationJava/PatternEditorJDialog.java
0 → 100644
... | ... | @@ -0,0 +1,253 @@ |
1 | +import java.awt.BorderLayout; | |
2 | +import java.awt.Color; | |
3 | +import java.awt.Component; | |
4 | +import java.awt.Dimension; | |
5 | +import java.awt.FlowLayout; | |
6 | +import java.awt.Font; | |
7 | +import java.awt.Frame; | |
8 | +import java.awt.event.ActionEvent; | |
9 | +import java.awt.event.ActionListener; | |
10 | +import java.awt.event.FocusEvent; | |
11 | +import java.awt.event.FocusListener; | |
12 | + | |
13 | +import javax.swing.Box; | |
14 | +import javax.swing.BoxLayout; | |
15 | +import javax.swing.JButton; | |
16 | +import javax.swing.JComboBox; | |
17 | +import javax.swing.JDialog; | |
18 | +import javax.swing.JFrame; | |
19 | +import javax.swing.JLabel; | |
20 | +import javax.swing.JPanel; | |
21 | +import javax.swing.JSlider; | |
22 | +import javax.swing.JTextField; | |
23 | + | |
24 | +public class PatternEditorJDialog extends JDialog implements ActionListener, FocusListener { | |
25 | + private static final long serialVersionUID = 1L; | |
26 | + private static final Font titleFont = new Font(new JLabel().getFont().getName(), Font.BOLD, 14); | |
27 | + private static final String[] fieldsNames = new String[] { | |
28 | + "Low time : ", //0 | |
29 | + "Rise time : ", //1 | |
30 | + "High time : ", //2 | |
31 | + "Fall time : ", //3 | |
32 | + "Low time : ", //4 | |
33 | + "Repeat : ", //5 | |
34 | + "Begin time : ", //6 | |
35 | + "Volume : ", //7 | |
36 | + "Path : ", //8 | |
37 | + "Duration : ", //9 | |
38 | + "Pattern time : ", //10 | |
39 | + "Total time : " //11 | |
40 | + }; | |
41 | + private void generateComponents() { | |
42 | + fields = new Component[fieldsNames.length]; | |
43 | + | |
44 | + // 7 textfields | |
45 | + for(int i=0; i<7; i++) { | |
46 | + fields[i] = new JTextField(10); | |
47 | + fields[i].addFocusListener(this); | |
48 | + } | |
49 | + | |
50 | + // 1 slider | |
51 | + fields[7] = new JSlider(0, 10, 8); | |
52 | + ((JSlider) fields[7]).setMajorTickSpacing(2); | |
53 | + ((JSlider) fields[7]).setMinorTickSpacing(1); | |
54 | + ((JSlider) fields[7]).setPaintTicks(true); | |
55 | + | |
56 | + // 1 combobox | |
57 | + fields[8] = new JComboBox<String>(MusicPath.pathNames); | |
58 | + | |
59 | + | |
60 | + // 1 textfields | |
61 | + fields[9] = new JTextField(10); | |
62 | + fields[9].addFocusListener(this); | |
63 | + | |
64 | + // 2 textfields disabled | |
65 | + for(int i=10; i<12; i++) { | |
66 | + fields[i] = new JTextField(10); | |
67 | + fields[i].setEnabled(false); | |
68 | + fields[i].addFocusListener(this); | |
69 | + fields[i].setForeground(Color.DARK_GRAY); | |
70 | + } | |
71 | + } | |
72 | + | |
73 | + private Component[] fields; | |
74 | + private JButton ok; | |
75 | + private JButton cancel; | |
76 | + private Music music = null; | |
77 | + | |
78 | + public PatternEditorJDialog(Frame parent) { this(parent, null); } | |
79 | + public PatternEditorJDialog(Frame parent, Music musicPrev) { | |
80 | + super(parent, "Pattern editor", true); | |
81 | + generateComponents(); | |
82 | + | |
83 | + // main panel | |
84 | + | |
85 | + JPanel mainPanel = new JPanel(new BorderLayout()); | |
86 | + getContentPane().add(mainPanel); | |
87 | + | |
88 | + // title | |
89 | + | |
90 | + JPanel titlePanel = new JPanel(new FlowLayout()); | |
91 | + JLabel title = new JLabel("Pattern parameters : "); | |
92 | + title.setFont(titleFont); | |
93 | + titlePanel.add(title); | |
94 | + mainPanel.add(titlePanel, BorderLayout.NORTH); | |
95 | + | |
96 | + // center panel | |
97 | + JPanel centerPanel = new JPanel(); | |
98 | + centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.LINE_AXIS)); | |
99 | + mainPanel.add(centerPanel, BorderLayout.CENTER); | |
100 | + //padding | |
101 | + centerPanel.add(Box.createRigidArea(new Dimension(5, 0))); | |
102 | + | |
103 | + // labels panel | |
104 | + JPanel labelsPanel = new JPanel(); | |
105 | + labelsPanel.setLayout(new BoxLayout(labelsPanel, BoxLayout.PAGE_AXIS)); | |
106 | + centerPanel.add(labelsPanel); | |
107 | + | |
108 | + // fields panel | |
109 | + JPanel fieldsPanel = new JPanel(); | |
110 | + fieldsPanel.setLayout(new BoxLayout(fieldsPanel, BoxLayout.PAGE_AXIS)); | |
111 | + centerPanel.add(fieldsPanel); | |
112 | + //padding | |
113 | + centerPanel.add(Box.createRigidArea(new Dimension(5, 0))); | |
114 | + | |
115 | + JLabel[] fieldsLabels = new JLabel[fieldsNames.length]; | |
116 | + for(int i=0; i<fields.length; i++) { | |
117 | + fieldsPanel.add(fields[i]); | |
118 | + | |
119 | + fieldsLabels[i] = new JLabel(fieldsNames[i]); | |
120 | + fieldsLabels[i].setAlignmentX(Component.RIGHT_ALIGNMENT); | |
121 | + fieldsLabels[i].setMaximumSize(new Dimension(fieldsLabels[i].getPreferredSize().width, fields[i].getPreferredSize().height)); | |
122 | + labelsPanel.add(fieldsLabels[i]); | |
123 | + } | |
124 | + | |
125 | + // buttons | |
126 | + | |
127 | + JPanel buttonsPanel = new JPanel(new FlowLayout()); | |
128 | + mainPanel.add(buttonsPanel, BorderLayout.SOUTH); | |
129 | + | |
130 | + ok = new JButton("Ok"); | |
131 | + ok.addActionListener(this); | |
132 | + buttonsPanel.add(ok); | |
133 | + | |
134 | + cancel = new JButton("Cancel"); | |
135 | + cancel.addActionListener(this); | |
136 | + buttonsPanel.add(cancel); | |
137 | + | |
138 | + setResizable(false); | |
139 | + pack(); | |
140 | + setLocationRelativeTo(null); | |
141 | + setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); | |
142 | + | |
143 | + | |
144 | + // load prev music | |
145 | + music = musicPrev; | |
146 | + if(musicPrev != null) | |
147 | + updateFeildsToMusic(); | |
148 | + | |
149 | + // format and compute disabled fields | |
150 | + updateFields(); | |
151 | + } | |
152 | + | |
153 | + private void updateFeildsToMusic() { | |
154 | + int[] pattern = music.getMusicPattern().getPattern(); | |
155 | + ((JTextField) fields[0]).setText(String.valueOf(pattern[0])); | |
156 | + ((JTextField) fields[1]).setText(String.valueOf(pattern[1])); | |
157 | + ((JTextField) fields[2]).setText(String.valueOf(pattern[2])); | |
158 | + ((JTextField) fields[3]).setText(String.valueOf(pattern[3])); | |
159 | + ((JTextField) fields[4]).setText(String.valueOf(pattern[4])); | |
160 | + | |
161 | + ((JTextField) fields[5]).setText(String.valueOf(music.getMusicPattern().getRepeat())); | |
162 | + ((JTextField) fields[6]).setText(String.valueOf(music.getMusicPattern().getBegin())); | |
163 | + | |
164 | + ((JSlider) fields[7]).setValue((int) (music.getVolume() * 10d)); | |
165 | + | |
166 | + MusicPath path = music.getMusicPath(); | |
167 | + ((JComboBox<?>) fields[8]).setSelectedIndex(path.getAnimation()); | |
168 | + | |
169 | + ((JTextField) fields[9]).setText(String.valueOf(path.getEffectDuration())); | |
170 | + } | |
171 | + | |
172 | + public Music showDialog() { | |
173 | + setVisible(true); | |
174 | + return music; | |
175 | + } | |
176 | + | |
177 | + @Override | |
178 | + public void actionPerformed(ActionEvent e) { | |
179 | + if(e.getSource() == ok) { | |
180 | + updateFields(); | |
181 | + | |
182 | + int lowTime = (int) Util.textToTick(((JTextField) fields[0]).getText()); | |
183 | + int raiseTime = (int) Util.textToTick(((JTextField) fields[1]).getText()); | |
184 | + int highTime = (int) Util.textToTick(((JTextField) fields[2]).getText()); | |
185 | + int fallTime = (int) Util.textToTick(((JTextField) fields[3]).getText()); | |
186 | + int pauseTime = (int) Util.textToTick(((JTextField) fields[4]).getText()); | |
187 | + int repeats = Integer.parseInt(((JTextField) fields[5]).getText()); | |
188 | + long beginTime = Util.textToTick(((JTextField) fields[6]).getText()); | |
189 | + | |
190 | + int animationId = ((JComboBox<?>) fields[8]).getSelectedIndex(); | |
191 | + int effectDuration = (int) Util.textToTick(((JTextField) fields[9]).getText()); | |
192 | + | |
193 | + MusicPattern musicPattern = new MusicPattern(new int[] {lowTime, raiseTime, highTime, fallTime, pauseTime}, repeats, beginTime); | |
194 | + MusicPath musicPath = new MusicPath(animationId, effectDuration); | |
195 | + double volume = (double) ((JSlider) fields[7]).getValue() / (double) ((JSlider) fields[7]).getMaximum(); | |
196 | + | |
197 | + //invalid params | |
198 | + if((lowTime == 0 && raiseTime == 0 && highTime == 0 && fallTime == 0 && pauseTime == 0) | |
199 | + || (repeats <= 0) | |
200 | + || (beginTime < 0) | |
201 | + || (effectDuration < 0)) { | |
202 | + music = null; | |
203 | + dispose(); | |
204 | + return; | |
205 | + } | |
206 | + | |
207 | + music = new Music(musicPattern, musicPath, volume); | |
208 | + | |
209 | + dispose(); | |
210 | + } else if(e.getSource() == cancel) { | |
211 | + music = null; | |
212 | + dispose(); | |
213 | + } | |
214 | + } | |
215 | + | |
216 | + public void updateFields() { | |
217 | + // format textfields | |
218 | + for(int i=0; i<fields.length; i++) { | |
219 | + if(fields[i] instanceof JTextField && i != 5) | |
220 | + ((JTextField) fields[i]).setText(Util.formatTime(((JTextField) fields[i]).getText())); | |
221 | + else if(i == 5) { | |
222 | + try { | |
223 | + int n = Integer.parseInt(((JTextField) fields[i]).getText()); | |
224 | + if(n < 1) | |
225 | + ((JTextField) fields[i]).setText("1"); | |
226 | + }catch (NumberFormatException e) { | |
227 | + ((JTextField) fields[i]).setText("1"); | |
228 | + } | |
229 | + } | |
230 | + } | |
231 | + | |
232 | + // compute patter time and total time | |
233 | + long lowTime = Util.textToTick(((JTextField) fields[0]).getText()); | |
234 | + long raiseTime = Util.textToTick(((JTextField) fields[1]).getText()); | |
235 | + long highTime = Util.textToTick(((JTextField) fields[2]).getText()); | |
236 | + long fallTime = Util.textToTick(((JTextField) fields[3]).getText()); | |
237 | + long pauseTime = Util.textToTick(((JTextField) fields[4]).getText()); | |
238 | + int repeats = Integer.parseInt(((JTextField) fields[5]).getText()); | |
239 | + | |
240 | + long patterTime = lowTime + raiseTime + highTime + fallTime + pauseTime; | |
241 | + ((JTextField) fields[10]).setText(Util.tickToText(patterTime)); | |
242 | + long totalTime = patterTime * repeats; | |
243 | + ((JTextField) fields[11]).setText(Util.tickToText(totalTime)); | |
244 | + } | |
245 | + | |
246 | + @Override | |
247 | + public void focusGained(FocusEvent e) {} | |
248 | + | |
249 | + @Override | |
250 | + public void focusLost(FocusEvent e) { | |
251 | + updateFields(); | |
252 | + } | |
253 | +} | ... | ... |
VRGNYMusicLights/Sources/PatternJPanel.java renamed to VRGNYMusicLights/Sources/ApplicationJava/PatternJPanel.java
... | ... | @@ -2,6 +2,7 @@ import java.awt.Color; |
2 | 2 | import java.awt.Dimension; |
3 | 3 | import java.awt.Graphics; |
4 | 4 | |
5 | +import javax.swing.JLabel; | |
5 | 6 | import javax.swing.JPanel; |
6 | 7 | |
7 | 8 | public class PatternJPanel extends JPanel { |
... | ... | @@ -9,6 +10,7 @@ public class PatternJPanel extends JPanel { |
9 | 10 | private static final int HEIGHT = 50; |
10 | 11 | private static final int PADDING = 2; |
11 | 12 | public static final int ZOOM_MULTIPLIER = 10; |
13 | + public static final int PATTERN_HEIGHT = (int) (HEIGHT + new JLabel(" ").getPreferredSize().height); | |
12 | 14 | |
13 | 15 | private Music music; |
14 | 16 | private TimeLineJPanel timeLine; |
... | ... | @@ -17,12 +19,12 @@ public class PatternJPanel extends JPanel { |
17 | 19 | public PatternJPanel(Music music, TimeLineJPanel timeLine) { |
18 | 20 | this.music = music; |
19 | 21 | this.timeLine = timeLine; |
20 | - end = transformZoon(music.getMusicPattern().getStop()); | |
22 | + end = Util.transformZoom(music.getMusicPattern().getStop(), timeLine.getZoomLevel()); | |
21 | 23 | setPreferredSize(new Dimension((int) end, HEIGHT)); |
22 | 24 | } |
23 | 25 | |
24 | 26 | public void refreshPreferedSize() { |
25 | - end = transformZoon(music.getMusicPattern().getStop()); | |
27 | + end = Util.transformZoom(music.getMusicPattern().getStop(), timeLine.getZoomLevel()); | |
26 | 28 | setPreferredSize(new Dimension((int) end, HEIGHT)); |
27 | 29 | } |
28 | 30 | |
... | ... | @@ -34,30 +36,23 @@ public class PatternJPanel extends JPanel { |
34 | 36 | super.paintComponent(g); |
35 | 37 | |
36 | 38 | g.setColor(Color.WHITE); |
37 | - int begin = transformZoon(music.getMusicPattern().getBegin()); | |
38 | - g.fillRect(begin, 0, end, HEIGHT); | |
39 | + int begin = Util.transformZoom(music.getMusicPattern().getBegin(), timeLine.getZoomLevel()); | |
40 | + g.fillRect(begin, 0, end - begin, HEIGHT); | |
39 | 41 | |
40 | 42 | MusicPattern pattern = music.getMusicPattern(); |
41 | 43 | g.setColor(Color.BLACK); |
42 | 44 | for(int i=0; i<pattern.getRepeat(); i++) { |
43 | - int repeatAddition = transformZoon(pattern.getTotalLength() * i) + begin; | |
45 | + int repeatAddition = Util.transformZoom(pattern.getTotalLength() * i, timeLine.getZoomLevel()) + begin; | |
44 | 46 | g.drawLine(repeatAddition, HEIGHT - PADDING, |
45 | - transformZoon(pattern.getPatternTiming()[0]) + repeatAddition, HEIGHT - PADDING); | |
46 | - g.drawLine(transformZoon(pattern.getPatternTiming()[0]) + repeatAddition, HEIGHT - PADDING, | |
47 | - transformZoon(pattern.getPatternTiming()[1]) + repeatAddition, PADDING); | |
48 | - g.drawLine(transformZoon(pattern.getPatternTiming()[1]) + repeatAddition, PADDING, | |
49 | - transformZoon(pattern.getPatternTiming()[2]) + repeatAddition, PADDING); | |
50 | - g.drawLine(transformZoon(pattern.getPatternTiming()[2]) + repeatAddition, PADDING, | |
51 | - transformZoon(pattern.getPatternTiming()[3]) + repeatAddition, HEIGHT - PADDING); | |
52 | - g.drawLine(transformZoon(pattern.getPatternTiming()[3]) + repeatAddition, HEIGHT - PADDING, | |
53 | - transformZoon(pattern.getPatternTiming()[4]) + repeatAddition, HEIGHT - PADDING); | |
47 | + Util.transformZoom(pattern.getPatternTiming()[0], timeLine.getZoomLevel()) + repeatAddition, HEIGHT - PADDING); | |
48 | + g.drawLine(Util.transformZoom(pattern.getPatternTiming()[0], timeLine.getZoomLevel()) + repeatAddition, HEIGHT - PADDING, | |
49 | + Util.transformZoom(pattern.getPatternTiming()[1], timeLine.getZoomLevel()) + repeatAddition, PADDING); | |
50 | + g.drawLine(Util.transformZoom(pattern.getPatternTiming()[1], timeLine.getZoomLevel()) + repeatAddition, PADDING, | |
51 | + Util.transformZoom(pattern.getPatternTiming()[2], timeLine.getZoomLevel()) + repeatAddition, PADDING); | |
52 | + g.drawLine(Util.transformZoom(pattern.getPatternTiming()[2], timeLine.getZoomLevel()) + repeatAddition, PADDING, | |
53 | + Util.transformZoom(pattern.getPatternTiming()[3], timeLine.getZoomLevel()) + repeatAddition, HEIGHT - PADDING); | |
54 | + g.drawLine(Util.transformZoom(pattern.getPatternTiming()[3], timeLine.getZoomLevel()) + repeatAddition, HEIGHT - PADDING, | |
55 | + Util.transformZoom(pattern.getPatternTiming()[4], timeLine.getZoomLevel()) + repeatAddition, HEIGHT - PADDING); | |
54 | 56 | } |
55 | 57 | } |
56 | - | |
57 | - private int transformZoon(int n) { | |
58 | - return transformZoon((long) n); | |
59 | - } | |
60 | - private int transformZoon(long n) { | |
61 | - return (int) ((double) n / (double) ZOOM_MULTIPLIER * timeLine.getZoomLevel()); | |
62 | - } | |
63 | 58 | } | ... | ... |
VRGNYMusicLights/Sources/PlayJPanel.java renamed to VRGNYMusicLights/Sources/ApplicationJava/PlayJPanel.java
1 | 1 | import java.awt.BorderLayout; |
2 | +import java.awt.Color; | |
2 | 3 | import java.awt.Font; |
3 | 4 | |
5 | +import javax.swing.BorderFactory; | |
4 | 6 | import javax.swing.Box; |
5 | 7 | import javax.swing.BoxLayout; |
6 | 8 | import javax.swing.JLabel; |
... | ... | @@ -12,6 +14,7 @@ public class PlayJPanel extends JPanel { |
12 | 14 | |
13 | 15 | public PlayJPanel(Interface interf, LightCanvasJPanel lightCanvas) { |
14 | 16 | super(new BorderLayout()); |
17 | + setBorder(BorderFactory.createMatteBorder(4, 0, 0, 0, Color.LIGHT_GRAY)); | |
15 | 18 | |
16 | 19 | // title |
17 | 20 | JLabel title = new JLabel("Visualizer :"); | ... | ... |
VRGNYMusicLights/Sources/SerialCom.java renamed to VRGNYMusicLights/Sources/ApplicationJava/SerialCom.java
VRGNYMusicLights/Sources/SerialComPortException.java renamed to VRGNYMusicLights/Sources/ApplicationJava/SerialComPortException.java
VRGNYMusicLights/Sources/SerialComWrongCallbackMethod.java renamed to VRGNYMusicLights/Sources/ApplicationJava/SerialComWrongCallbackMethod.java
VRGNYMusicLights/Sources/SerialCommands.java renamed to VRGNYMusicLights/Sources/ApplicationJava/SerialCommands.java
VRGNYMusicLights/Sources/SerialPortChooserDialog.java renamed to VRGNYMusicLights/Sources/ApplicationJava/SerialPortChooserDialog.java
VRGNYMusicLights/Sources/TimeLineJList.java renamed to VRGNYMusicLights/Sources/ApplicationJava/TimeLineJList.java
... | ... | @@ -21,16 +21,9 @@ public class TimeLineJList extends JList<Music> { |
21 | 21 | g.setColor(Color.BLACK); |
22 | 22 | |
23 | 23 | int maxHeight = getPreferredSize().height; |
24 | - int maxWidth = getPreferredSize().width; | |
25 | 24 | |
26 | - int mark = transformZoon(interf.tick); | |
27 | - if(mark > maxWidth) | |
28 | - mark = maxWidth; | |
25 | + int mark = Util.transformZoom(interf.tick, interf.timeLinePanel.getZoomLevel()); | |
29 | 26 | |
30 | 27 | g.fillRect(mark, 0, MARK_WIDTH, maxHeight); |
31 | 28 | } |
32 | - | |
33 | - private int transformZoon(long n) { | |
34 | - return (int) ((double) n / (double) PatternJPanel.ZOOM_MULTIPLIER * interf.timeLinePanel.getZoomLevel()); | |
35 | - } | |
36 | 29 | } | ... | ... |
VRGNYMusicLights/Sources/TimeLineJPanel.java renamed to VRGNYMusicLights/Sources/ApplicationJava/TimeLineJPanel.java
... | ... | @@ -2,6 +2,8 @@ import java.awt.Dimension; |
2 | 2 | import java.awt.Font; |
3 | 3 | import java.awt.event.ActionEvent; |
4 | 4 | import java.awt.event.ActionListener; |
5 | +import java.awt.event.AdjustmentEvent; | |
6 | +import java.awt.event.AdjustmentListener; | |
5 | 7 | import java.awt.event.FocusEvent; |
6 | 8 | import java.awt.event.FocusListener; |
7 | 9 | import java.awt.event.MouseWheelEvent; |
... | ... | @@ -14,10 +16,13 @@ import javax.swing.JLabel; |
14 | 16 | import javax.swing.JPanel; |
15 | 17 | import javax.swing.JScrollBar; |
16 | 18 | import javax.swing.JScrollPane; |
19 | +import javax.swing.JSlider; | |
17 | 20 | import javax.swing.JTextField; |
18 | 21 | import javax.swing.ListSelectionModel; |
22 | +import javax.swing.event.ChangeEvent; | |
23 | +import javax.swing.event.ChangeListener; | |
19 | 24 | |
20 | -public class TimeLineJPanel extends JPanel implements MouseWheelListener, FocusListener, ActionListener { | |
25 | +public class TimeLineJPanel extends JPanel implements MouseWheelListener, FocusListener, ActionListener, ChangeListener, AdjustmentListener { | |
21 | 26 | private static final long serialVersionUID = 1L; |
22 | 27 | private static final Font titleFont = new Font(new JLabel().getFont().getName(), Font.BOLD, 14); |
23 | 28 | |
... | ... | @@ -32,8 +37,9 @@ public class TimeLineJPanel extends JPanel implements MouseWheelListener, FocusL |
32 | 37 | private Interface interf; |
33 | 38 | private JTextField currentTick; |
34 | 39 | private JLabel maxTicks; |
40 | + private JPanel scrollPanel; | |
35 | 41 | |
36 | - public TimeLineJPanel(Interface interf, MusicList list) { | |
42 | + public TimeLineJPanel(Interface interf) { | |
37 | 43 | this.interf = interf; |
38 | 44 | setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); |
39 | 45 | |
... | ... | @@ -58,71 +64,129 @@ public class TimeLineJPanel extends JPanel implements MouseWheelListener, FocusL |
58 | 64 | |
59 | 65 | add(timingPanel); |
60 | 66 | |
61 | - // timeline | |
67 | + // scroll pane | |
62 | 68 | |
63 | - listModel = new DefaultListModel<>(); | |
64 | - for(Music music : list.getList()) | |
65 | - listModel.addElement(music); | |
69 | + scrollPanel = new JPanel(); | |
70 | + scrollPanel.setLayout(new BoxLayout(scrollPanel, BoxLayout.PAGE_AXIS)); | |
71 | + scrollPane = new JScrollPane(scrollPanel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); | |
72 | + scrollPane.addMouseWheelListener(this); | |
73 | + scrollPane.setWheelScrollingEnabled(false); | |
74 | + scrollPane.getHorizontalScrollBar().addAdjustmentListener(this); | |
75 | + scrollPane.setPreferredSize(new Dimension(800, 400)); | |
76 | + add(scrollPane); | |
77 | + | |
78 | + // slider | |
79 | + | |
80 | + interf.timeSlider = new JSlider(JSlider.HORIZONTAL, 0, 0, 0); | |
81 | + interf.timeSlider.setMajorTickSpacing(1000); | |
82 | + interf.timeSlider.setMinorTickSpacing(500); | |
83 | + interf.timeSlider.setPaintTicks(true); | |
84 | + interf.timeSlider.setAlignmentX(LEFT_ALIGNMENT); | |
85 | + interf.timeSlider.setEnabled(false); | |
86 | + interf.timeSlider.setUI(new CustomSliderUI(interf.timeSlider)); | |
87 | + interf.timeSlider.addChangeListener(this); | |
88 | + scrollPanel.add(interf.timeSlider); | |
89 | + | |
90 | + // timeline | |
66 | 91 | |
92 | + listModel = new DefaultListModel<>(); | |
93 | + for(Music music : interf.musicList.getList()) | |
94 | + listModel.addElement(music); | |
67 | 95 | interf.timeLineList = new TimeLineJList(listModel, interf); |
68 | 96 | musicRenderer = new MusicRenderer(this); |
69 | 97 | interf.timeLineList.setCellRenderer(musicRenderer); |
70 | 98 | interf.timeLineList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); |
71 | - scrollPane = new JScrollPane(interf.timeLineList, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); | |
72 | - scrollPane.addMouseWheelListener(this); | |
73 | - scrollPane.setWheelScrollingEnabled(false); | |
74 | - scrollPane.setPreferredSize(new Dimension(800, 400)); | |
75 | - add(scrollPane); | |
99 | + interf.timeLineList.setAlignmentX(LEFT_ALIGNMENT); | |
100 | + scrollPanel.add(interf.timeLineList); | |
76 | 101 | } |
77 | 102 | |
78 | 103 | public double getZoomLevel() { return zoomLevel; } |
79 | 104 | |
80 | - public void updateList(MusicList list) { | |
105 | + public void updateList() { | |
106 | + final MusicList musicList = interf.musicList; | |
107 | + | |
81 | 108 | listModel.clear(); |
82 | - for(Music music : list.getList()) | |
83 | - listModel.addElement(music); | |
109 | + for(Music music : musicList.getList()) | |
110 | + listModel.addElement(music); | |
111 | + | |
112 | + // compute max slider | |
113 | + long maxTick = 0; | |
114 | + for(Music music : musicList.getList()) { | |
115 | + if(music.getMusicPattern().getStop() > maxTick) | |
116 | + maxTick = music.getMusicPattern().getStop(); | |
117 | + } | |
118 | + interf.timeSlider.setMaximum((int) maxTick); | |
119 | + | |
120 | + // update need a delay and have to be call with another thread (note sure why...) | |
121 | + new Thread(new Runnable() { | |
122 | + @Override | |
123 | + public void run() { | |
124 | + try { | |
125 | + Thread.sleep(10); | |
126 | + } catch (InterruptedException e) { | |
127 | + e.printStackTrace(); | |
128 | + } | |
129 | + if(musicList.getList().size() != 0) | |
130 | + updateTimeLine(0); | |
131 | + } | |
132 | + }).start(); | |
84 | 133 | } |
85 | 134 | |
86 | 135 | public void updateTick() { |
87 | 136 | currentTick.setText(Util.tickToText(interf.tick)); |
88 | - long maxTick = 0; | |
89 | - for(PatternJPanel pattern : musicRenderer.patterns) { | |
90 | - pattern.refreshPreferedSize(); | |
91 | - long tick = pattern.getMusic().getMusicPattern().getStop(); | |
92 | - if(tick > maxTick) | |
93 | - maxTick = tick; | |
94 | - } | |
95 | - maxTicks.setText(Util.tickToText(maxTick) + " (MM:ss:ms)"); | |
137 | + long maxTick = 0; | |
138 | + for(PatternJPanel pattern : musicRenderer.patterns) { | |
139 | + pattern.refreshPreferedSize(); | |
140 | + long tick = pattern.getMusic().getMusicPattern().getStop(); | |
141 | + if(tick > maxTick) | |
142 | + maxTick = tick; | |
143 | + } | |
144 | + maxTicks.setText(Util.tickToText(maxTick) + " (mm:ss:ms)"); | |
96 | 145 | } |
97 | 146 | |
98 | 147 | public void mouseWheelMoved(MouseWheelEvent e) { |
99 | 148 | if(e.getSource() == scrollPane) { |
100 | - if (e.isControlDown()) { | |
101 | - if(e.getWheelRotation() < 0) | |
102 | - zoomLevel *= (double) e.getWheelRotation() * -1.1; | |
103 | - else | |
104 | - zoomLevel *= (double) e.getWheelRotation() / 1.1; | |
105 | - | |
106 | - int maxWidth = 0; | |
107 | - for(PatternJPanel pattern : musicRenderer.patterns) { | |
108 | - pattern.refreshPreferedSize(); | |
109 | - int width = pattern.getEnd(); | |
110 | - if(width > maxWidth) | |
111 | - maxWidth = width; | |
112 | - } | |
113 | - | |
114 | - interf.timeLineList.setPreferredSize(new Dimension(maxWidth, interf.getPreferredSize().height)); | |
115 | - scrollPane.repaint(); | |
116 | - scrollPane.getViewport().revalidate(); | |
117 | - } else if(e.isShiftDown()) { | |
118 | - JScrollBar sb = scrollPane.getHorizontalScrollBar(); | |
119 | - sb.setValue(sb.getValue() + e.getWheelRotation() * SCROLL_SPEED_HORIZONTAL); | |
120 | - } else { | |
121 | - JScrollBar sb = scrollPane.getVerticalScrollBar(); | |
122 | - sb.setValue(sb.getValue() + e.getWheelRotation() * SCROLL_SPEED_VERTICAL); | |
123 | - } | |
149 | + if (e.isControlDown()) { | |
150 | + if(interf.musicList.getList().size() != 0) | |
151 | + updateTimeLine(e.getWheelRotation()); | |
152 | + } else if(e.isShiftDown()) { | |
153 | + JScrollBar sb = scrollPane.getHorizontalScrollBar(); | |
154 | + sb.setValue(sb.getValue() + e.getWheelRotation() * SCROLL_SPEED_HORIZONTAL); | |
155 | + } else { | |
156 | + JScrollBar sb = scrollPane.getVerticalScrollBar(); | |
157 | + sb.setValue(sb.getValue() + e.getWheelRotation() * SCROLL_SPEED_VERTICAL); | |
158 | + } | |
159 | + } | |
160 | + } | |
161 | + | |
162 | + public void updateTimeLine(int wheelRot) { | |
163 | + if(wheelRot < 0) | |
164 | + zoomLevel *= (double) wheelRot * -1.1; | |
165 | + else if (wheelRot > 0) | |
166 | + zoomLevel *= (double) wheelRot / 1.1; | |
167 | + | |
168 | + interf.timeSlider.setEnabled(musicRenderer.patterns.size() != 0); | |
169 | + int maxWidth = 0; | |
170 | + if(musicRenderer.patterns.size() == 0) { | |
171 | + interf.timeSlider.setValue(0); | |
172 | + maxWidth = (int) (scrollPane.getPreferredSize().width - new JScrollBar().getPreferredSize().getWidth()) - 1; | |
173 | + } else { | |
174 | + for(PatternJPanel pattern : musicRenderer.patterns) { | |
175 | + pattern.refreshPreferedSize(); | |
176 | + int width = pattern.getEnd(); | |
177 | + if(width > maxWidth) | |
178 | + maxWidth = width; | |
179 | + } | |
124 | 180 | } |
125 | - } | |
181 | + | |
182 | + interf.timeSlider.setMaximumSize(new Dimension(maxWidth, interf.timeSlider.getPreferredSize().height)); | |
183 | + interf.timeLineList.setMaximumSize(new Dimension(maxWidth, PatternJPanel.PATTERN_HEIGHT * musicRenderer.patterns.size())); | |
184 | + interf.timeLineList.setPreferredSize(new Dimension(maxWidth, PatternJPanel.PATTERN_HEIGHT * musicRenderer.patterns.size())); | |
185 | + scrollPanel.setPreferredSize(new Dimension(maxWidth, PatternJPanel.PATTERN_HEIGHT * musicRenderer.patterns.size())); | |
186 | + scrollPane.repaint(); | |
187 | + scrollPane.getViewport().revalidate(); | |
188 | + scrollPanel.revalidate(); | |
189 | + } | |
126 | 190 | |
127 | 191 | @Override |
128 | 192 | public void focusLost(FocusEvent e) { |
... | ... | @@ -143,4 +207,22 @@ public class TimeLineJPanel extends JPanel implements MouseWheelListener, FocusL |
143 | 207 | if(e.getSource() == currentTick) |
144 | 208 | interf.getContentPane().requestFocus(); |
145 | 209 | } |
210 | + | |
211 | + @Override | |
212 | + public void stateChanged(ChangeEvent e) { | |
213 | + if(e.getSource() == interf.timeSlider) { | |
214 | + interf.tick = interf.timeSlider.getValue(); | |
215 | + interf.computeTick(); | |
216 | + } | |
217 | + } | |
218 | + | |
219 | + @Override | |
220 | + public void adjustmentValueChanged(AdjustmentEvent e) { | |
221 | + if(e.getSource() == scrollPane.getHorizontalScrollBar()) { | |
222 | + musicRenderer.setInfoPadding(scrollPane.getHorizontalScrollBar().getValue()); | |
223 | + scrollPane.repaint(); | |
224 | + scrollPane.getViewport().revalidate(); | |
225 | + scrollPanel.revalidate(); | |
226 | + } | |
227 | + } | |
146 | 228 | } | ... | ... |
VRGNYMusicLights/Sources/Util.java renamed to VRGNYMusicLights/Sources/ApplicationJava/Util.java
... | ... | @@ -43,4 +43,12 @@ public class Util { |
43 | 43 | |
44 | 44 | return str; |
45 | 45 | } |
46 | + | |
47 | + public static String formatTime(String str) { | |
48 | + return tickToText(textToTick(str)); | |
49 | + } | |
50 | + | |
51 | + public static int transformZoom(long n, double zoom) { | |
52 | + return (int) ((double) n / (double) PatternJPanel.ZOOM_MULTIPLIER * zoom); | |
53 | + } | |
46 | 54 | } | ... | ... |
No preview for this file type
VRGNYMusicLights/Sources/icons/backward.png renamed to VRGNYMusicLights/Sources/ApplicationJava/icons/backward.png
436 Bytes
VRGNYMusicLights/Sources/icons/forward.png renamed to VRGNYMusicLights/Sources/ApplicationJava/icons/forward.png
412 Bytes
VRGNYMusicLights/Sources/icons/pause.png renamed to VRGNYMusicLights/Sources/ApplicationJava/icons/pause.png
295 Bytes
VRGNYMusicLights/Sources/icons/play.png renamed to VRGNYMusicLights/Sources/ApplicationJava/icons/play.png
364 Bytes
VRGNYMusicLights/Sources/icons/stop.png renamed to VRGNYMusicLights/Sources/ApplicationJava/icons/stop.png
320 Bytes