Commit 278cdee04a1413adc98d137837b0f5303da7f7b2

Authored by pfrison
1 parent a89c030d

VRGNYMusicLights timeline beginning

VRGNYMusicLights/Sources/AnimationPlayer.java
... ... @@ -10,8 +10,7 @@ import javax.swing.JPanel;
10 10 public class AnimationPlayer extends JPanel implements ActionListener {
11 11 private static final long serialVersionUID = 1L;
12 12  
13   - private LightCanvasJPanel lightCanvas;
14   - private MusicList musicList;
  13 + private Interface interf;
15 14  
16 15 private JButton backward;
17 16 private JButton stop;
... ... @@ -19,10 +18,9 @@ public class AnimationPlayer extends JPanel implements ActionListener {
19 18 private JButton pause;
20 19 private JButton forward;
21 20  
22   - private long tick = 0;
23 21 private boolean go = false;
24 22 private boolean stopClock = false;
25   - private static final int TICK_JUMP = 20;
  23 + private static final int TICK_JUMP = 10;
26 24 private Thread tickClock = new Thread(new Runnable() {
27 25 @Override
28 26 public void run() {
... ... @@ -34,25 +32,24 @@ public class AnimationPlayer extends JPanel implements ActionListener {
34 32 }
35 33  
36 34 long before = System.currentTimeMillis();
37   - lightCanvas.paintLights(musicList.render(tick));
38   - tick += TICK_JUMP;
  35 + interf.computeTick();
  36 + interf.tick += TICK_JUMP;
39 37 long after = System.currentTimeMillis();
40 38  
41 39 if(after - before < TICK_JUMP) {
42   - try { Thread.sleep(10 - after + before);}
  40 + try { Thread.sleep(TICK_JUMP - after + before);}
43 41 catch (InterruptedException ignored) {}
44 42 } else if(after - before > TICK_JUMP) {
45   - System.err.println("Animation were slowed down by " + String.valueOf(after - before - 10) + " ticks !");
  43 + System.err.println("Animation were slowed down by " + String.valueOf(after - before - TICK_JUMP) + " ticks !");
46 44 }
47 45 }
48 46 }
49 47 });
50 48 public void stopTickClock() {stopClock = true;}
51 49  
52   - public AnimationPlayer(LightCanvasJPanel lightCanvas, MusicList musicList) { this(lightCanvas, musicList, BoxLayout.LINE_AXIS); }
53   - public AnimationPlayer(LightCanvasJPanel lightCanvas, MusicList musicList, int direction) {
54   - this.lightCanvas = lightCanvas;
55   - this.musicList = musicList;
  50 + public AnimationPlayer(Interface interf) { this(interf, BoxLayout.LINE_AXIS); }
  51 + public AnimationPlayer(Interface interf, int direction) {
  52 + this.interf = interf;
56 53  
57 54 setLayout(new BoxLayout(this, direction));
58 55  
... ... @@ -90,20 +87,22 @@ public class AnimationPlayer extends JPanel implements ActionListener {
90 87  
91 88 @Override
92 89 public void actionPerformed(ActionEvent e) {
93   - // TODO player actions
94 90 if(e.getSource() == backward) {
95   - tick -= 500;
96   - if(tick < 0)
97   - tick = 0;
  91 + interf.tick -= 100;
  92 + if(interf.tick < 0)
  93 + interf.tick = 0;
  94 + interf.computeTick();
98 95 }else if(e.getSource() == stop) {
99 96 go = false;
100   - tick = 0;
  97 + interf.tick = 0;
  98 + interf.computeTick();
101 99 }else if(e.getSource() == play) {
102 100 go = true;
103 101 }else if(e.getSource() == pause) {
104 102 go = false;
105 103 }else if(e.getSource() == forward) {
106   - tick += 500;
  104 + interf.tick += 100;
  105 + interf.computeTick();
107 106 }
108 107 }
109 108 }
... ...
VRGNYMusicLights/Sources/Interface.java
1 1 import java.awt.BorderLayout;
2   -import java.awt.Font;
3 2 import java.awt.event.WindowAdapter;
4 3 import java.awt.event.WindowEvent;
5 4  
6 5 import javax.swing.JFrame;
7   -import javax.swing.JLabel;
8 6 import javax.swing.JPanel;
9 7  
10 8 public class Interface extends JFrame{
11 9 private static final long serialVersionUID = 1L;
12   - private static final Font titleFont = new Font(new JLabel().getFont().getName(), Font.BOLD, 14);
13   - private static final Font defaultFont = new Font(new JLabel().getFont().getName(), Font.PLAIN, new JLabel().getFont().getSize());
  10 + //private static final Font titleFont = new Font(new JLabel().getFont().getName(), Font.BOLD, 14);
  11 + //private static final Font defaultFont = new Font(new JLabel().getFont().getName(), Font.PLAIN, new JLabel().getFont().getSize());
14 12  
15   - private MusicList musicList;
16   - private AnimationPlayer animPlayer;
  13 + protected MusicList musicList;
  14 + protected AnimationPlayer animPlayer;
  15 + protected TimeLineJPanel timeLinePanel;
  16 + protected TimeLineJList timeLineList;
  17 + protected LightCanvasJPanel lightCanvas;
  18 + protected long tick = 0;
17 19  
18 20 public Interface(MusicList musicList, final Runnable executeOnClose) {
19 21 super("VRGNYMusicLights");
... ... @@ -22,6 +24,7 @@ public class Interface extends JFrame{
22 24 populateWindow();
23 25 pack();
24 26 setLocationRelativeTo(null); // center window
  27 + getContentPane().requestFocus();
25 28  
26 29 addWindowListener(new WindowAdapter() {
27 30 @Override
... ... @@ -35,34 +38,18 @@ public class Interface extends JFrame{
35 38 });
36 39 }
37 40  
  41 + protected void computeTick() {
  42 + lightCanvas.paintLights(musicList.render(tick));
  43 + timeLineList.repaint();
  44 + timeLinePanel.updateTick();
  45 + }
  46 +
38 47 private void populateWindow() {
39 48 JPanel mainPanel = new JPanel(new BorderLayout());
40   - addPlayPanel(mainPanel);
41   - addTimeLine(mainPanel);
  49 + timeLinePanel = new TimeLineJPanel(this, musicList);
  50 + mainPanel.add(timeLinePanel, BorderLayout.CENTER);
  51 + lightCanvas = new LightCanvasJPanel();
  52 + mainPanel.add(new PlayJPanel(this, lightCanvas), BorderLayout.SOUTH);
42 53 add(mainPanel);
43 54 }
44   -
45   - private void addPlayPanel(JPanel parent) {
46   - JPanel playPanel = new JPanel(new BorderLayout());
47   -
48   - // title
49   - JLabel title = new JLabel("Visualizer :");
50   - title.setFont(titleFont);
51   - playPanel.add(title, BorderLayout.NORTH);
52   -
53   - // lights
54   - LightCanvasJPanel lightCanvas = new LightCanvasJPanel();
55   - playPanel.add(lightCanvas, BorderLayout.CENTER);
56   -
57   - // controls
58   - animPlayer = new AnimationPlayer(lightCanvas, musicList);
59   - animPlayer.setAlignmentX(CENTER_ALIGNMENT);
60   - playPanel.add(animPlayer, BorderLayout.SOUTH);
61   -
62   - parent.add(playPanel, BorderLayout.SOUTH);
63   - }
64   -
65   - private void addTimeLine(JPanel parent) {
66   - JPanel timeLine = new JPanel();
67   - }
68 55 }
... ...
VRGNYMusicLights/Sources/InvalidPatternException.java
... ... @@ -3,6 +3,6 @@ public class InvalidPatternException extends RuntimeException {
3 3 private static final long serialVersionUID = 1L;
4 4  
5 5 public InvalidPatternException() {
6   - super("Invalid pattern given. Length must be equal to 4.");
  6 + super("Invalid pattern given. Length must be equal to 5.");
7 7 }
8 8 }
... ...
VRGNYMusicLights/Sources/Main.java
... ... @@ -2,6 +2,7 @@ import javax.swing.JOptionPane;
2 2  
3 3 /* TODO list :
4 4 * - keyboard listener for animation player (play / pause = space, forward = semicolon, backward = comma, stop = backspace)
  5 + * - pattern timeline info to follow scroll horizontal ?
5 6 */
6 7 public class Main {
7 8 public static void main(String[] args) throws InterruptedException {
... ... @@ -22,8 +23,13 @@ public class Main {
22 23 MusicList musicList = new MusicList(null);
23 24 musicList.addMusic(
24 25 new Music(
25   - new MusicPattern(new int[] {1000, 0, 0, 1000}, 1000, 0),
26   - new MusicPath(MusicPath.CENTER_IN, 1000),
  26 + new MusicPattern(new int[] {0, 10, 100, 10, 100}, 100, 1000),
  27 + new MusicPath(MusicPath.CENTER_OUT, 1000),
  28 + 1));
  29 + musicList.addMusic(
  30 + new Music(
  31 + new MusicPattern(new int[] {0, 10, 100, 10, 100}, 1, 0),
  32 + new MusicPath(MusicPath.CENTER_OUT, 1000),
27 33 1));
28 34  
29 35 Interface i = new Interface(musicList, new Runnable() {
... ...
VRGNYMusicLights/Sources/Music.java
... ... @@ -10,6 +10,8 @@ public class Music {
10 10 this.volume = volume;
11 11 }
12 12  
  13 + public MusicPattern getMusicPattern() { return pattern; }
  14 +
13 15 public double[] render(long tick) {
14 16 double[] lights = new double[lightTickDelais.length];
15 17 for(int i=0; i<lights.length; i++)
... ...
VRGNYMusicLights/Sources/MusicList.java
... ... @@ -9,6 +9,7 @@ public class MusicList {
9 9 musics = new ArrayList<>();
10 10 }
11 11  
  12 + public ArrayList<Music> getList() { return musics; }
12 13 public void addMusic(Music music) { musics.add(music); }
13 14 public void deleteMusic(int index) { musics.remove(index); }
14 15  
... ...
VRGNYMusicLights/Sources/MusicPath.java
... ... @@ -75,34 +75,34 @@ public class MusicPath {
75 75 || animation == CENTER_IN) {
76 76 switch (animation) {
77 77 case VERTICAL_DOWN:
78   - ticksDelais[i] += tickLateVerticalDown(LIGHT_COORDS[i][1]);
  78 + ticksDelais[i] -= tickLateVerticalDown(LIGHT_COORDS[i][1]);
79 79 break;
80 80 case VERTICAL_UP:
81   - ticksDelais[i] += tickLateVerticalUp(LIGHT_COORDS[i][1]);
  81 + ticksDelais[i] -= tickLateVerticalUp(LIGHT_COORDS[i][1]);
82 82 break;
83 83 case HORIZONTAL_TO_LEFT:
84   - ticksDelais[i] += tickLateHorizontalToLeft(LIGHT_COORDS[i][0]);
  84 + ticksDelais[i] -= tickLateHorizontalToLeft(LIGHT_COORDS[i][0]);
85 85 break;
86 86 case HORIZONTAL_TO_RIGHT:
87   - ticksDelais[i] += tickLateHorizontalToRight(LIGHT_COORDS[i][0]);
  87 + ticksDelais[i] -= tickLateHorizontalToRight(LIGHT_COORDS[i][0]);
88 88 break;
89 89 case DIAGONAL_TOP_RIGHT_DOWN_LEFT:
90   - ticksDelais[i] += tickLateDiagTRDL(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]);
  90 + ticksDelais[i] -= tickLateDiagTRDL(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]);
91 91 break;
92 92 case DIAGONAL_DOWN_LEFT_TOP_RIGHT:
93   - ticksDelais[i] += tickLateDiagDLTR(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]);
  93 + ticksDelais[i] -= tickLateDiagDLTR(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]);
94 94 break;
95 95 case DIAGONAL_TOP_LEFT_DOWN_RIGHT:
96   - ticksDelais[i] += tickLateDiagTLDR(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]);
  96 + ticksDelais[i] -= tickLateDiagTLDR(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]);
97 97 break;
98 98 case DIAGONAL_DOWN_RIGHT_TOP_LEFT:
99   - ticksDelais[i] += tickLateDiagDRTL(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]);
  99 + ticksDelais[i] -= tickLateDiagDRTL(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]);
100 100 break;
101 101 case CENTER_OUT:
102   - ticksDelais[i] += tickLateCenterOut(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]);
  102 + ticksDelais[i] -= tickLateCenterOut(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]);
103 103 break;
104 104 case CENTER_IN:
105   - ticksDelais[i] += tickLateCenterIn(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]);
  105 + ticksDelais[i] -= tickLateCenterIn(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]);
106 106 break;
107 107 }
108 108 }
... ... @@ -111,16 +111,16 @@ public class MusicPath {
111 111 return ticksDelais;
112 112 }
113 113  
114   - private int tickLateVerticalDown(double y) {return (int) ((1-y) * effectDuration);}
115   - private int tickLateVerticalUp(double y) {return (int) (y * effectDuration);}
116   - private int tickLateHorizontalToRight(double x) {return (int) ((1-x) * effectDuration);}
117   - private int tickLateHorizontalToLeft(double x) {return (int) (x * effectDuration);}
118   - private int tickLateDiagTRDL(double x, double y) {return (int) ((x - y) / 2d * (double) effectDuration);}
119   - private int tickLateDiagDLTR(double x, double y) {return (int) ((-x + y) / 2d * (double) effectDuration);}
120   - private int tickLateDiagDRTL(double x, double y) {return (int) ((x + y) / 2d * (double) effectDuration);}
121   - private int tickLateDiagTLDR(double x, double y) {return (int) ((-x - y) / 2d * (double) effectDuration);}
122   - private int tickLateCenterOut(double x, double y) {return (int) ((1 - (x-0.5)*(x-0.5) - (y-0.5)*(y-0.5)) * 2 * (double) effectDuration);}
123   - private int tickLateCenterIn(double x, double y) {return (int) (((x-0.5)*(x-0.5) + (y-0.5)*(y-0.5)) * 2 * (double) effectDuration);}
  114 + private int tickLateVerticalDown(double y) {return (int) (y * effectDuration);}
  115 + private int tickLateVerticalUp(double y) {return (int) ((1-y) * effectDuration);}
  116 + private int tickLateHorizontalToRight(double x) {return (int) (x * effectDuration);}
  117 + private int tickLateHorizontalToLeft(double x) {return (int) ((1 - x) * effectDuration);}
  118 + private int tickLateDiagTRDL(double x, double y) {return (int) ((1 - x + y) / 2d * (double) effectDuration);}
  119 + private int tickLateDiagDLTR(double x, double y) {return (int) ((1 + x - y) / 2d * (double) effectDuration);}
  120 + private int tickLateDiagTLDR(double x, double y) {return (int) ((x + y) / 2d * (double) effectDuration);}
  121 + private int tickLateDiagDRTL(double x, double y) {return (int) ((2 - x - y) / 2d * (double) effectDuration);}
  122 + private int tickLateCenterOut(double x, double y) {return (int) (((x-0.5)*(x-0.5) + (y-0.5)*(y-0.5)) * 2 * (double) effectDuration);}
  123 + private int tickLateCenterIn(double x, double y) {return (int) ((0.5d - (x-0.5)*(x-0.5) - (y-0.5)*(y-0.5)) * 2 * (double) effectDuration);}
124 124  
125 125 public int getNumberOfLights() {
126 126 return this.lightsCoords.length;
... ...
VRGNYMusicLights/Sources/MusicPattern.java
... ... @@ -5,37 +5,48 @@ public class MusicPattern {
5 5 * 1 : rise time
6 6 * 2 : high time
7 7 * 3 : fall time
  8 + * 4 : low time
8 9 */
9 10 private int[] pattern; // in ms
10   - private int totalLentgh;
11   - private int[] patternTiming = new int[4]; // in ms
  11 + private int totalLength;
  12 + private int[] patternTiming = new int[5]; // in ms
12 13 private long begin; // in ms
13 14 private long stop; // in ms
  15 + private int repeat;
14 16  
15 17 public MusicPattern(int[] pattern, int repeat, long begin) {
16   - if(pattern.length != 4)
  18 + if(pattern.length != 5)
17 19 throw new InvalidPatternException();
18 20 this.pattern = pattern;
19   - this.totalLentgh = pattern[0] + pattern[1] + pattern[2] + pattern[3];
  21 + this.totalLength = pattern[0] + pattern[1] + pattern[2] + pattern[3] + pattern[4];
20 22 this.patternTiming[0] = pattern[0];
21   - for(int i=1; i<4; i++)
  23 + for(int i=1; i<5; i++)
22 24 this.patternTiming[i] = this.patternTiming[i-1] + pattern[i];
23 25 this.begin = begin;
24   - this.stop = repeat * totalLentgh;
  26 + this.stop = repeat * totalLength;
  27 + this.repeat = repeat;
25 28 }
  29 +
  30 + public int[] getPatternTiming() { return patternTiming; }
  31 + public long getStop() { return stop; }
  32 + public long getBegin() { return begin; }
  33 + public int getRepeat() { return repeat; }
  34 + public int getTotalLength () { return totalLength; }
26 35  
27 36 public double render(long tick) { // tick in ms
28 37 if(tick <= begin)
29 38 return 0;
30 39 if(tick >= stop)
31 40 return 0;
32   - int tickMod = (int) (tick % totalLentgh);
  41 + int tickMod = (int) (tick % totalLength);
33 42 if(tickMod < patternTiming[0])
34 43 return 0;
35 44 if(tickMod < patternTiming[1])
36 45 return (double) (tickMod - patternTiming[0]) / (double) (pattern[1]);
37 46 if(tickMod < patternTiming[2])
38 47 return 1;
39   - return 1 - ((double) (tickMod - patternTiming[2]) / (double) (pattern[3]));
  48 + if(tickMod < patternTiming[3])
  49 + return 1 - ((double) (tickMod - patternTiming[2]) / (double) (pattern[3]));
  50 + return 0;
40 51 }
41 52 }
... ...
VRGNYMusicLights/Sources/MusicRenderer.java 0 → 100644
... ... @@ -0,0 +1,54 @@
  1 +import java.awt.Color;
  2 +import java.awt.Component;
  3 +import java.util.ArrayList;
  4 +
  5 +import javax.swing.Box;
  6 +import javax.swing.BoxLayout;
  7 +import javax.swing.JLabel;
  8 +import javax.swing.JList;
  9 +import javax.swing.JPanel;
  10 +import javax.swing.ListCellRenderer;
  11 +
  12 +public class MusicRenderer extends JPanel implements ListCellRenderer<Music> {
  13 + private static final long serialVersionUID = 1L;
  14 + private static final Color DEFAULT_BACKGROUND = new JPanel().getBackground();
  15 +
  16 + private TimeLineJPanel timeLine;
  17 +
  18 + public ArrayList<PatternJPanel> patterns;
  19 +
  20 + public MusicRenderer(TimeLineJPanel timeLine) {
  21 + this.timeLine = timeLine;
  22 + this.patterns = new ArrayList<>();
  23 + }
  24 +
  25 + @Override
  26 + public Component getListCellRendererComponent(JList<? extends Music> list, Music music, int index,
  27 + boolean isSelected, boolean cellHasFocus) {
  28 + removeAll();
  29 +
  30 + if(isSelected) {
  31 + setBackground(Color.LIGHT_GRAY);
  32 + } else {
  33 + setBackground(DEFAULT_BACKGROUND);
  34 + }
  35 +
  36 + setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
  37 +
  38 + JPanel infoPanel = new JPanel();
  39 + 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.createHorizontalGlue());
  43 + add(infoPanel);
  44 +
  45 + PatternJPanel pattern = new PatternJPanel(music, timeLine);
  46 + if(patterns.size() > index)
  47 + patterns.set(index, pattern);
  48 + else
  49 + patterns.add(pattern);
  50 + add(pattern);
  51 +
  52 + return this;
  53 + }
  54 +}
... ...
VRGNYMusicLights/Sources/PatternJPanel.java 0 → 100644
... ... @@ -0,0 +1,63 @@
  1 +import java.awt.Color;
  2 +import java.awt.Dimension;
  3 +import java.awt.Graphics;
  4 +
  5 +import javax.swing.JPanel;
  6 +
  7 +public class PatternJPanel extends JPanel {
  8 + private static final long serialVersionUID = 1L;
  9 + private static final int HEIGHT = 50;
  10 + private static final int PADDING = 2;
  11 + public static final int ZOOM_MULTIPLIER = 10;
  12 +
  13 + private Music music;
  14 + private TimeLineJPanel timeLine;
  15 + private int end;
  16 +
  17 + public PatternJPanel(Music music, TimeLineJPanel timeLine) {
  18 + this.music = music;
  19 + this.timeLine = timeLine;
  20 + end = transformZoon(music.getMusicPattern().getStop());
  21 + setPreferredSize(new Dimension((int) end, HEIGHT));
  22 + }
  23 +
  24 + public void refreshPreferedSize() {
  25 + end = transformZoon(music.getMusicPattern().getStop());
  26 + setPreferredSize(new Dimension((int) end, HEIGHT));
  27 + }
  28 +
  29 + public int getEnd() { return end; }
  30 + public Music getMusic() { return music; }
  31 +
  32 + @Override
  33 + protected void paintComponent(Graphics g) {
  34 + super.paintComponent(g);
  35 +
  36 + g.setColor(Color.WHITE);
  37 + int begin = transformZoon(music.getMusicPattern().getBegin());
  38 + g.fillRect(begin, 0, end, HEIGHT);
  39 +
  40 + MusicPattern pattern = music.getMusicPattern();
  41 + g.setColor(Color.BLACK);
  42 + for(int i=0; i<pattern.getRepeat(); i++) {
  43 + int repeatAddition = transformZoon(pattern.getTotalLength() * i) + begin;
  44 + 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);
  54 + }
  55 + }
  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 +}
... ...
VRGNYMusicLights/Sources/PlayJPanel.java 0 → 100644
... ... @@ -0,0 +1,32 @@
  1 +import java.awt.BorderLayout;
  2 +import java.awt.Font;
  3 +
  4 +import javax.swing.Box;
  5 +import javax.swing.BoxLayout;
  6 +import javax.swing.JLabel;
  7 +import javax.swing.JPanel;
  8 +
  9 +public class PlayJPanel extends JPanel {
  10 + private static final long serialVersionUID = 1L;
  11 + private static final Font titleFont = new Font(new JLabel().getFont().getName(), Font.BOLD, 14);
  12 +
  13 + public PlayJPanel(Interface interf, LightCanvasJPanel lightCanvas) {
  14 + super(new BorderLayout());
  15 +
  16 + // title
  17 + JLabel title = new JLabel("Visualizer :");
  18 + title.setFont(titleFont);
  19 + add(title, BorderLayout.NORTH);
  20 +
  21 + // lights
  22 + JPanel centerPanel = new JPanel();
  23 + centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.LINE_AXIS));
  24 + centerPanel.add(Box.createHorizontalGlue());
  25 + centerPanel.add(lightCanvas);
  26 + add(centerPanel, BorderLayout.CENTER);
  27 +
  28 + // controls
  29 + interf.animPlayer = new AnimationPlayer(interf);
  30 + add(interf.animPlayer, BorderLayout.SOUTH);
  31 + }
  32 +}
... ...
VRGNYMusicLights/Sources/TimeLineJList.java 0 → 100644
... ... @@ -0,0 +1,36 @@
  1 +import java.awt.Color;
  2 +import java.awt.Graphics;
  3 +
  4 +import javax.swing.JList;
  5 +import javax.swing.ListModel;
  6 +
  7 +public class TimeLineJList extends JList<Music> {
  8 + private static final long serialVersionUID = 1L;
  9 + private static final int MARK_WIDTH = 2;
  10 +
  11 + private Interface interf;
  12 +
  13 + public TimeLineJList(ListModel<Music> dataModel, Interface interf) {
  14 + super(dataModel);
  15 + this.interf = interf;
  16 + }
  17 +
  18 + @Override
  19 + protected void paintComponent(Graphics g) {
  20 + super.paintComponent(g);
  21 + g.setColor(Color.BLACK);
  22 +
  23 + int maxHeight = getPreferredSize().height;
  24 + int maxWidth = getPreferredSize().width;
  25 +
  26 + int mark = transformZoon(interf.tick);
  27 + if(mark > maxWidth)
  28 + mark = maxWidth;
  29 +
  30 + g.fillRect(mark, 0, MARK_WIDTH, maxHeight);
  31 + }
  32 +
  33 + private int transformZoon(long n) {
  34 + return (int) ((double) n / (double) PatternJPanel.ZOOM_MULTIPLIER * interf.timeLinePanel.getZoomLevel());
  35 + }
  36 +}
... ...
VRGNYMusicLights/Sources/TimeLineJPanel.java 0 → 100644
... ... @@ -0,0 +1,146 @@
  1 +import java.awt.Dimension;
  2 +import java.awt.Font;
  3 +import java.awt.event.ActionEvent;
  4 +import java.awt.event.ActionListener;
  5 +import java.awt.event.FocusEvent;
  6 +import java.awt.event.FocusListener;
  7 +import java.awt.event.MouseWheelEvent;
  8 +import java.awt.event.MouseWheelListener;
  9 +
  10 +import javax.swing.Box;
  11 +import javax.swing.BoxLayout;
  12 +import javax.swing.DefaultListModel;
  13 +import javax.swing.JLabel;
  14 +import javax.swing.JPanel;
  15 +import javax.swing.JScrollBar;
  16 +import javax.swing.JScrollPane;
  17 +import javax.swing.JTextField;
  18 +import javax.swing.ListSelectionModel;
  19 +
  20 +public class TimeLineJPanel extends JPanel implements MouseWheelListener, FocusListener, ActionListener {
  21 + private static final long serialVersionUID = 1L;
  22 + private static final Font titleFont = new Font(new JLabel().getFont().getName(), Font.BOLD, 14);
  23 +
  24 + private static final int SCROLL_SPEED_HORIZONTAL = 30;
  25 + private static final int SCROLL_SPEED_VERTICAL = 30;
  26 +
  27 + private DefaultListModel<Music> listModel;
  28 + private double zoomLevel = 1;
  29 +
  30 + private JScrollPane scrollPane;
  31 + private MusicRenderer musicRenderer;
  32 + private Interface interf;
  33 + private JTextField currentTick;
  34 + private JLabel maxTicks;
  35 +
  36 + public TimeLineJPanel(Interface interf, MusicList list) {
  37 + this.interf = interf;
  38 + setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
  39 +
  40 + // timing infos
  41 + JPanel timingPanel = new JPanel();
  42 + timingPanel.setLayout(new BoxLayout(timingPanel, BoxLayout.LINE_AXIS));
  43 +
  44 + JLabel title = new JLabel("Timeline : ");
  45 + title.setFont(titleFont);
  46 + timingPanel.add(title);
  47 +
  48 + currentTick = new JTextField("00:00.000", 8);
  49 + currentTick.setMaximumSize( currentTick.getPreferredSize() );
  50 + currentTick.addFocusListener(this);
  51 + currentTick.addActionListener(this);
  52 + timingPanel.add(currentTick);
  53 +
  54 + maxTicks = new JLabel(" / 00:00.0000 (MM:ss:ms)");
  55 + timingPanel.add(maxTicks);
  56 +
  57 + timingPanel.add(Box.createHorizontalGlue());
  58 +
  59 + add(timingPanel);
  60 +
  61 + // timeline
  62 +
  63 + listModel = new DefaultListModel<>();
  64 + for(Music music : list.getList())
  65 + listModel.addElement(music);
  66 +
  67 + interf.timeLineList = new TimeLineJList(listModel, interf);
  68 + musicRenderer = new MusicRenderer(this);
  69 + interf.timeLineList.setCellRenderer(musicRenderer);
  70 + 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);
  76 + }
  77 +
  78 + public double getZoomLevel() { return zoomLevel; }
  79 +
  80 + public void updateList(MusicList list) {
  81 + listModel.clear();
  82 + for(Music music : list.getList())
  83 + listModel.addElement(music);
  84 + }
  85 +
  86 + public void updateTick() {
  87 + 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)");
  96 + }
  97 +
  98 + public void mouseWheelMoved(MouseWheelEvent e) {
  99 + 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 + }
  124 + }
  125 + }
  126 +
  127 + @Override
  128 + public void focusLost(FocusEvent e) {
  129 + if(e.getSource() == currentTick) {
  130 + interf.tick = Util.textToTick(currentTick.getText());
  131 + currentTick.setText(Util.tickToText(interf.tick));
  132 + interf.computeTick();
  133 + }
  134 + }
  135 + @Override
  136 + public void focusGained(FocusEvent e) {
  137 + if(e.getSource() == currentTick)
  138 + currentTick.setCaretPosition(currentTick.getDocument().getLength());
  139 + }
  140 +
  141 + @Override
  142 + public void actionPerformed(ActionEvent e) {
  143 + if(e.getSource() == currentTick)
  144 + interf.getContentPane().requestFocus();
  145 + }
  146 +}
... ...
VRGNYMusicLights/Sources/Util.java 0 → 100644
... ... @@ -0,0 +1,46 @@
  1 +
  2 +public class Util {
  3 + public static long textToTick(String str) {
  4 + if(str == null || str.equals(""))
  5 + return 0;
  6 + String[] strs = str.split(":|\\.");
  7 + long ticks = 0;
  8 +
  9 + try {
  10 + switch (strs.length) {
  11 + case 1:
  12 + ticks += Integer.parseInt(strs[0]);
  13 + break;
  14 + case 2:
  15 + ticks += Integer.parseInt(strs[1]);
  16 + ticks += Integer.parseInt(strs[0]) * 1000;
  17 + break;
  18 + case 3:
  19 + ticks += Integer.parseInt(strs[2]);
  20 + ticks += Integer.parseInt(strs[1]) * 1000;
  21 + ticks += Integer.parseInt(strs[0]) * 60000;
  22 + break;
  23 + }
  24 + } catch (NumberFormatException e) {
  25 + return 0;
  26 + }
  27 + return ticks;
  28 + }
  29 +
  30 + public static String tickToText(long tick) {
  31 + String str = "";
  32 +
  33 + if(tick > 5900000)
  34 + str += "99:";
  35 + else
  36 + str += String.format("%02d", (int) ((double) tick / 60000d)) + ":";
  37 +
  38 + tick -= (int) ((double) tick / 60000d) * 60000;
  39 + str += String.format("%02d", (int) ((double) tick / 1000d)) + ".";
  40 +
  41 + tick -= (int) ((double) tick / 1000d) * 1000;
  42 + str += String.format("%03d", tick);
  43 +
  44 + return str;
  45 + }
  46 +}
... ...