import java.awt.Dimension; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelListener; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.DefaultListModel; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollBar; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.ListSelectionModel; public class TimeLineJPanel extends JPanel implements MouseWheelListener, FocusListener, ActionListener { private static final long serialVersionUID = 1L; private static final Font titleFont = new Font(new JLabel().getFont().getName(), Font.BOLD, 14); private static final int SCROLL_SPEED_HORIZONTAL = 30; private static final int SCROLL_SPEED_VERTICAL = 30; private DefaultListModel listModel; private double zoomLevel = 1; private JScrollPane scrollPane; private MusicRenderer musicRenderer; private Interface interf; private JTextField currentTick; private JLabel maxTicks; public TimeLineJPanel(Interface interf, MusicList list) { this.interf = interf; setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); // timing infos JPanel timingPanel = new JPanel(); timingPanel.setLayout(new BoxLayout(timingPanel, BoxLayout.LINE_AXIS)); JLabel title = new JLabel("Timeline : "); title.setFont(titleFont); timingPanel.add(title); currentTick = new JTextField("00:00.000", 8); currentTick.setMaximumSize( currentTick.getPreferredSize() ); currentTick.addFocusListener(this); currentTick.addActionListener(this); timingPanel.add(currentTick); maxTicks = new JLabel(" / 00:00.0000 (MM:ss:ms)"); timingPanel.add(maxTicks); timingPanel.add(Box.createHorizontalGlue()); add(timingPanel); // timeline listModel = new DefaultListModel<>(); for(Music music : list.getList()) listModel.addElement(music); interf.timeLineList = new TimeLineJList(listModel, interf); musicRenderer = new MusicRenderer(this); interf.timeLineList.setCellRenderer(musicRenderer); interf.timeLineList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); scrollPane = new JScrollPane(interf.timeLineList, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); scrollPane.addMouseWheelListener(this); scrollPane.setWheelScrollingEnabled(false); scrollPane.setPreferredSize(new Dimension(800, 400)); add(scrollPane); } public double getZoomLevel() { return zoomLevel; } public void updateList(MusicList list) { listModel.clear(); for(Music music : list.getList()) listModel.addElement(music); } public void updateTick() { currentTick.setText(Util.tickToText(interf.tick)); long maxTick = 0; for(PatternJPanel pattern : musicRenderer.patterns) { pattern.refreshPreferedSize(); long tick = pattern.getMusic().getMusicPattern().getStop(); if(tick > maxTick) maxTick = tick; } maxTicks.setText(Util.tickToText(maxTick) + " (MM:ss:ms)"); } public void mouseWheelMoved(MouseWheelEvent e) { if(e.getSource() == scrollPane) { if (e.isControlDown()) { if(e.getWheelRotation() < 0) zoomLevel *= (double) e.getWheelRotation() * -1.1; else zoomLevel *= (double) e.getWheelRotation() / 1.1; int maxWidth = 0; for(PatternJPanel pattern : musicRenderer.patterns) { pattern.refreshPreferedSize(); int width = pattern.getEnd(); if(width > maxWidth) maxWidth = width; } interf.timeLineList.setPreferredSize(new Dimension(maxWidth, interf.getPreferredSize().height)); scrollPane.repaint(); scrollPane.getViewport().revalidate(); } else if(e.isShiftDown()) { JScrollBar sb = scrollPane.getHorizontalScrollBar(); sb.setValue(sb.getValue() + e.getWheelRotation() * SCROLL_SPEED_HORIZONTAL); } else { JScrollBar sb = scrollPane.getVerticalScrollBar(); sb.setValue(sb.getValue() + e.getWheelRotation() * SCROLL_SPEED_VERTICAL); } } } @Override public void focusLost(FocusEvent e) { if(e.getSource() == currentTick) { interf.tick = Util.textToTick(currentTick.getText()); currentTick.setText(Util.tickToText(interf.tick)); interf.computeTick(); } } @Override public void focusGained(FocusEvent e) { if(e.getSource() == currentTick) currentTick.setCaretPosition(currentTick.getDocument().getLength()); } @Override public void actionPerformed(ActionEvent e) { if(e.getSource() == currentTick) interf.getContentPane().requestFocus(); } }