Mercurial > hg > cmdp
view src/uk/ac/qmul/eecs/depic/daw/gui/ArrangeWindow.java @ 4:473da40f3d39 tip
added html formatting to Daw/package-info.java
author | Fiore Martin <f.martin@qmul.ac.uk> |
---|---|
date | Thu, 25 Feb 2016 17:50:09 +0000 |
parents | 3074a84ef81e |
children |
line wrap: on
line source
/* Cross-Modal DAW Prototype - Prototype of a simple Cross-Modal Digital Audio Workstation. Copyright (C) 2015 Queen Mary University of London (http://depic.eecs.qmul.ac.uk/) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package uk.ac.qmul.eecs.depic.daw.gui; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.List; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.KeyStroke; import javax.swing.border.Border; import uk.ac.qmul.eecs.depic.daw.Selection; import uk.ac.qmul.eecs.depic.daw.SoundWave; import uk.ac.qmul.eecs.depic.daw.SoundWaveEvent; import uk.ac.qmul.eecs.depic.daw.SoundWaveListener; /** * * The panel containing the audio tracks. * * Tracks are arranged in a scrollable BoxLayout. * */ public class ArrangeWindow extends JPanel implements PropertyChangeListener, SoundWaveListener { private static final long serialVersionUID = 1L; public static final Color BACKGROUND_COLOR = new Color(226,226,226); public static final int SPACE_BETWEEN_TRACKS = 5; public static final Border BORDER_UNSELECTED = BorderFactory.createCompoundBorder( BorderFactory.createEmptyBorder(1, 0, 1, 0), BorderFactory.createMatteBorder(1, 0, 1, 0, Color.GRAY)); public static final Border BORDER_SELECTED = BorderFactory.createCompoundBorder( BorderFactory.createMatteBorder(1, 0, 1, 0, new Color(214, 193, 99)), BorderFactory.createMatteBorder(1, 0, 1, 0, Color.GRAY)); /* tracks panel contains the rule and audio tracks */ private JScrollPane tracksPanelScroll; /* view of the trackPanelScroll and panel where all the audio tracks are places */ private JPanel tracksPanel; /* left panel with AudioTrackParameters */ private JPanel parametersPanel; private Rule rule; private int currentTrackIndex; private List<AudioTrack> tracks; private List<AudioTrackParameters> audioTrackParameters; private List<Component> spacesBetweenTracks; private List<Component> spacesBetweenTrackParameters; private MouseInteraction mouseInteraction; public ArrangeWindow(){ tracks = new ArrayList<>(); audioTrackParameters = new ArrayList<>(); spacesBetweenTracks = new ArrayList<>(); spacesBetweenTrackParameters = new ArrayList<>(); mouseInteraction = new MouseInteraction(); setLayout(new BorderLayout()); setBackground(BACKGROUND_COLOR); /* left panel: header (of the same height as rule) and parameters */ parametersPanel = new JPanel(); parametersPanel.setLayout(new BoxLayout(parametersPanel,BoxLayout.Y_AXIS)); parametersPanel.add(Box.createRigidArea(new Dimension(247,Rule.HEIGHT+3))); parametersPanel.setBackground(BACKGROUND_COLOR); add(parametersPanel,BorderLayout.WEST); /* right panel: scrollable panel with rule and tracks as header*/ tracksPanel = new JPanel(); tracksPanel.setLayout(new BoxLayout(tracksPanel,BoxLayout.Y_AXIS)); tracksPanel.setBackground(BACKGROUND_COLOR); rule = new Rule(); rule.setBackground(BACKGROUND_COLOR); tracksPanelScroll = new JScrollPane(tracksPanel, JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); /* disable the scrolling via the left-right keys to let the cursor scrub handler * take over when the track is focused */ tracksPanelScroll.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "none"); tracksPanelScroll.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "none"); /* setPreferredSize important, otherwise the view port gets resized to the track size * * as soon as the window is resized and therefore the scroll bar disappear */ tracksPanelScroll.setPreferredSize(new Dimension(500,500)); /* rule is set as the header of the scroll pane with audio tracks */ tracksPanelScroll.setColumnHeaderView(rule); add(tracksPanelScroll, BorderLayout.CENTER); currentTrackIndex = -1; } /** * Adds a track to this component. The added track is automatically set as the current track. * * Adding a track that's already in the arrange window will have no effect. * * @param track the new track to add. It must be a track that is not currently * contained in this arrange window */ public void addTrack(AudioTrack track){ if(tracks.contains(track)) return; AudioTrackParameters trackParameters = new AudioTrackParameters(track,1); /* install the mouse listener */ track.addMouseListener(mouseInteraction); trackParameters.addMouseListener(mouseInteraction); // FIXME verify /* add track and parameters in the respective lists */ tracks.add(track); audioTrackParameters.add(trackParameters); Component box1 = Box.createVerticalStrut(SPACE_BETWEEN_TRACKS); Component box2 = Box.createVerticalStrut(SPACE_BETWEEN_TRACKS); spacesBetweenTracks.add(box1); spacesBetweenTrackParameters.add(box2); /* add track and parameters in the respective panels */ parametersPanel.add(box1); parametersPanel.add(trackParameters); tracksPanel.add(box2); tracksPanel.add(track); /* set the new track as the current */ setCurrentTrack(getTracksCount()-1); /* set the label. Users will count starting from 1 and not from 0 */ trackParameters.setLabel("new Track "+(getCurrentTrackIndex()+1)); repaint(); } public AudioTrack getTrackAt(int index){ return tracks.get(index); } public AudioTrackParameters getTrackParametersAt(int index){ return audioTrackParameters.get(index); } /** * * @return the current track or {@code null} if there are no tracks * in this arrange window */ public AudioTrack getCurrentTrack(){ if(currentTrackIndex == -1) return null; return tracks.get(currentTrackIndex); } /** * Sets the track at the specified index as current. * * @param index the index of the new current track * @throws ArrayIndexOutOfBoundsException if {@code index} is lower than 0 or greater or equal to {@code getTracksCount()} * * */ public void setCurrentTrack(int index){ /* removes this from the listeners of the previous current track */ if(currentTrackIndex != -1){ AudioTrack previousTrack = getTrackAt(currentTrackIndex); previousTrack.removePropertyChangeListener(this); previousTrack.getSoundWave().removeSoundWaveListener(this); previousTrack.setBorder(BORDER_UNSELECTED); audioTrackParameters.get(currentTrackIndex).setBorder(BORDER_UNSELECTED); } currentTrackIndex = index; AudioTrack currentTrack = getTrackAt(currentTrackIndex); /* install listeners in the new audio track */ currentTrack.addPropertyChangeListener(this); currentTrack.getSoundWave().addSoundWaveListener(this); /* set the borders */ currentTrack.setBorder(BORDER_SELECTED); audioTrackParameters.get(currentTrackIndex).setBorder(BORDER_SELECTED); rule.setAudioTrack(getTrackAt(currentTrackIndex)); } /** * * @return the index of the currently selected track or {@code -1} if no track * is open in the arrange window */ public int getCurrentTrackIndex(){ return currentTrackIndex; } /** * Returns the number of tracks in this arrange window. * * @return the number of tracks in this arrange window */ public int getTracksCount(){ return tracks.size(); } public Rule getRule(){ return rule; } /** * * On {@code SELECTION_CHANGED} event from the current audio track, updates the other * tracks accordingly. * * This enforces a unique selection and cursor position over the whole arrange window * * @param evt the sound wave event * */ @Override public void update(SoundWaveEvent evt) { if(SoundWaveEvent.SCAN.equals(evt.getType())){ for(int i=0; i< getTracksCount(); i++){ SoundWave wave = getTrackAt(i).getSoundWave(); /* only change selection if it's not the one that triggered the event */ if(!wave.equals(evt.getSource())){ wave.scan((Integer)evt.getArgs()); } } } if(SoundWaveEvent.POSITION_CHANGED.equals(evt.getType()) ){ for(AudioTrack track : tracks){ if(!track.getSoundWave().equals(evt.getSource())){ track.getSoundWave().setPosition((Integer)evt.getArgs()); } } /* this is called from the current audio track sound wave. The * * selection is changed in the other audio tracks accordingly */ //SoundWave currentWave = evt.getSource(); // for(int i=0; i< getTracksCount(); i++){ // SoundWave wave = getTrackAt(i).getSoundWave(); // /* only change selection if it's not the one that triggered the event */ // if(!wave.equals(currentWave)){ // wave.setSelection((Selection)evt.getArgs()); // } // } } } private class MouseInteraction extends MouseAdapter { @Override public void mousePressed(MouseEvent e){ Component c = e.getComponent(); int index = tracks.lastIndexOf(c); if(index == getCurrentTrackIndex()){ return; }else if(index != -1){ setCurrentTrack(index); return; } index = audioTrackParameters.lastIndexOf(c); if(index == getCurrentTrackIndex()){ return; }else if(index != -1){ setCurrentTrack(index); return; } } } @Override public void propertyChange(PropertyChangeEvent evt) { switch(evt.getPropertyName()){ case "mouseDragSelection" : { Selection selection = (Selection)evt.getNewValue(); for(AudioTrack track : tracks){ if(!track.equals(evt.getSource())){ track.trackInteraction.setMouseSelection( selection.getStart(), selection.getEnd()); } } } break; } } }