f@0
|
1 /*
|
f@0
|
2 Cross-Modal DAW Prototype - Prototype of a simple Cross-Modal Digital Audio Workstation.
|
f@0
|
3
|
f@0
|
4 Copyright (C) 2015 Queen Mary University of London (http://depic.eecs.qmul.ac.uk/)
|
f@0
|
5
|
f@0
|
6 This program is free software: you can redistribute it and/or modify
|
f@0
|
7 it under the terms of the GNU General Public License as published by
|
f@0
|
8 the Free Software Foundation, either version 3 of the License, or
|
f@0
|
9 (at your option) any later version.
|
f@0
|
10
|
f@0
|
11 This program is distributed in the hope that it will be useful,
|
f@0
|
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
f@0
|
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
f@0
|
14 GNU General Public License for more details.
|
f@0
|
15
|
f@0
|
16 You should have received a copy of the GNU General Public License
|
f@0
|
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
|
f@0
|
18 */
|
f@0
|
19 package uk.ac.qmul.eecs.depic.daw.gui;
|
f@0
|
20
|
f@0
|
21 import java.awt.BorderLayout;
|
f@0
|
22 import java.awt.Dimension;
|
f@0
|
23 import java.awt.Toolkit;
|
f@0
|
24 import java.awt.event.InputEvent;
|
f@0
|
25 import java.awt.event.KeyEvent;
|
f@0
|
26
|
f@0
|
27 import javax.swing.Action;
|
f@0
|
28 import javax.swing.Box;
|
f@0
|
29 import javax.swing.InputMap;
|
f@0
|
30 import javax.swing.JButton;
|
f@0
|
31 import javax.swing.JComponent;
|
f@0
|
32 import javax.swing.JFrame;
|
f@0
|
33 import javax.swing.JMenu;
|
f@0
|
34 import javax.swing.JMenuBar;
|
f@0
|
35 import javax.swing.JMenuItem;
|
f@0
|
36 import javax.swing.JPanel;
|
f@0
|
37 import javax.swing.JScrollPane;
|
f@0
|
38 import javax.swing.JToggleButton;
|
f@0
|
39 import javax.swing.JToolBar;
|
f@0
|
40 import javax.swing.KeyStroke;
|
f@0
|
41 import javax.swing.SwingUtilities;
|
f@0
|
42 import javax.swing.UIManager;
|
f@0
|
43 import javax.swing.UIManager.LookAndFeelInfo;
|
f@0
|
44 import javax.swing.UnsupportedLookAndFeelException;
|
f@0
|
45
|
f@0
|
46 import uk.ac.qmul.eecs.depic.daw.Daw;
|
f@0
|
47 import uk.ac.qmul.eecs.depic.daw.gui.actions.Actions;
|
f@0
|
48
|
f@2
|
49 /**
|
f@2
|
50 *
|
f@2
|
51 * The main frame of this program.
|
f@2
|
52 *
|
f@2
|
53 */
|
f@0
|
54 public class MainFrame extends JFrame {
|
f@0
|
55 private static final long serialVersionUID = 1L;
|
f@0
|
56 private Actions actions;
|
f@0
|
57 private ArrangeWindow arrangeWindow;
|
f@0
|
58 private JToolBar transportBar;
|
f@0
|
59
|
f@0
|
60 public MainFrame(){
|
f@0
|
61 super("Cross-Modal DAW Prototype");
|
f@0
|
62 /* makes the overwritten getContentPane() correct */
|
f@0
|
63 setContentPane(new JPanel());
|
f@0
|
64
|
f@0
|
65 /* try and set system look and feel */
|
f@0
|
66
|
f@0
|
67 try {
|
f@0
|
68 for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
|
f@0
|
69 if ("Nimbus".equals(info.getName())) {
|
f@0
|
70 UIManager.setLookAndFeel(info.getClassName());
|
f@0
|
71 break;
|
f@0
|
72 }
|
f@0
|
73 }
|
f@0
|
74 } catch (Exception e) {
|
f@0
|
75 // If Nimbus is not available, you can set the GUI to another look and feel.
|
f@0
|
76 try {
|
f@0
|
77 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
f@0
|
78 SwingUtilities.updateComponentTreeUI(this);
|
f@0
|
79 } catch (ClassNotFoundException|InstantiationException|IllegalAccessException|UnsupportedLookAndFeelException e1) {
|
f@0
|
80 // do nothing and stick with java look&feel
|
f@0
|
81 }
|
f@0
|
82 }
|
f@0
|
83
|
f@0
|
84 setDefaultCloseOperation(EXIT_ON_CLOSE); // FIXME make own close operation
|
f@0
|
85
|
f@0
|
86 JPanel contentPane = (JPanel)getContentPane();
|
f@0
|
87 contentPane.setLayout(new BorderLayout());
|
f@0
|
88
|
f@0
|
89 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
|
f@0
|
90
|
f@0
|
91 int screenWidth = (int)screenSize.getWidth();
|
f@0
|
92 int screenHeight = (int)screenSize.getHeight();
|
f@0
|
93
|
f@0
|
94 setLocation(screenWidth / 16, screenHeight / 16);
|
f@0
|
95 contentPane.setPreferredSize(new Dimension(
|
f@0
|
96 screenWidth * 5 / 8, screenHeight * 5 / 8));
|
f@0
|
97
|
f@0
|
98 arrangeWindow = new ArrangeWindow();
|
f@0
|
99 transportBar = new JToolBar(){
|
f@0
|
100 private static final long serialVersionUID = 1L;
|
f@0
|
101
|
f@0
|
102 @Override
|
f@0
|
103 protected JButton createActionComponent(Action a){
|
f@0
|
104 /* add the accessible name to the button using the action name */
|
f@0
|
105 JButton b = super.createActionComponent(a);
|
f@0
|
106
|
f@0
|
107
|
f@0
|
108 b.getAccessibleContext().setAccessibleName((String)a.getValue(Action.NAME));
|
f@0
|
109 return b;
|
f@0
|
110 }
|
f@0
|
111 };
|
f@0
|
112 contentPane.add(transportBar,BorderLayout.NORTH);
|
f@0
|
113 /* arrange window scroll contains the tracks and the Track parameters. The *
|
f@0
|
114 * scroll bar appears when the number of tracks exceeds the screen size */
|
f@0
|
115 JScrollPane arrangeWindowScroll = new JScrollPane(arrangeWindow);
|
f@0
|
116 arrangeWindowScroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
|
f@0
|
117 arrangeWindowScroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
|
f@0
|
118 contentPane.add(arrangeWindowScroll,BorderLayout.CENTER);
|
f@0
|
119
|
f@0
|
120
|
f@0
|
121 /* remove actions for scrolling left and right: the content of this scroll pane only *
|
f@0
|
122 * grows in height when track are added. Moreover this actions conflict with the *
|
f@0
|
123 * scrubbing through the audio track with right and left arrow keys */
|
f@0
|
124 InputMap im = arrangeWindowScroll.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
|
f@0
|
125 im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT,0),"none");
|
f@0
|
126 im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT,0),"none");
|
f@0
|
127
|
f@0
|
128
|
f@0
|
129 getArrangeWindow().addTrack(new AudioTrack(Daw.getSoundEngineFactory().createSoundWave()));
|
f@0
|
130
|
f@0
|
131 actions = new Actions(this);
|
f@0
|
132 initMenu(actions);
|
f@0
|
133 initTransportBar(actions);
|
f@0
|
134 initScrubActions();
|
f@0
|
135 }
|
f@0
|
136
|
f@0
|
137 protected void initMenu(Actions actions){
|
f@0
|
138 JMenuBar menuBar = new JMenuBar();
|
f@0
|
139 this.setJMenuBar(menuBar);
|
f@0
|
140
|
f@0
|
141 /* -- File Menu -- */
|
f@0
|
142 JMenu fileMenu = new JMenu(actions.getVoidAction("file"));
|
f@0
|
143 menuBar.add(fileMenu);
|
f@0
|
144
|
f@0
|
145 fileMenu.add( new JMenuItem(actions.open()));
|
f@0
|
146 fileMenu.add(new JMenuItem(actions.close()));
|
f@0
|
147 fileMenu.addSeparator();
|
f@0
|
148
|
f@0
|
149 fileMenu.add(new JMenuItem(actions.properties()));
|
f@0
|
150
|
f@0
|
151 fileMenu.addSeparator();
|
f@0
|
152 fileMenu.add(new JMenuItem(actions.exit()));
|
f@0
|
153
|
f@0
|
154
|
f@0
|
155 /* -- Edit Menu -- */
|
f@0
|
156 JMenu editMenu = new JMenu(actions.getVoidAction("edit"));
|
f@0
|
157 menuBar.add(editMenu);
|
f@0
|
158
|
f@0
|
159 editMenu.add(new JMenuItem(actions.cut()));
|
f@0
|
160 editMenu.add(new JMenuItem(actions.copy()));
|
f@0
|
161 editMenu.add(new JMenuItem(actions.paste()));
|
f@0
|
162 editMenu.add(new JMenuItem(actions.insert()));
|
f@0
|
163
|
f@0
|
164 /* -- View Menu -- */
|
f@0
|
165 JMenu viewMenu = new JMenu(actions.getVoidAction("view"));
|
f@0
|
166 menuBar.add(viewMenu);
|
f@0
|
167
|
f@0
|
168 viewMenu.add(new JMenuItem(actions.zoomIn()));
|
f@0
|
169 viewMenu.add(new JMenuItem(actions.zoomOut()));
|
f@0
|
170 viewMenu.add(new JMenuItem(actions.showDb()));
|
f@0
|
171 viewMenu.add(new JMenuItem(actions.generatePeaks()));
|
f@0
|
172 viewMenu.add(new JMenuItem(actions.findNextPoint()));
|
f@0
|
173 viewMenu.add(new JMenuItem(actions.findPreviousPoint()));
|
f@0
|
174
|
f@0
|
175 /* -- Track Menu --*/
|
f@0
|
176 JMenu trackMenu = new JMenu(actions.getVoidAction("track"));
|
f@0
|
177 menuBar.add(trackMenu);
|
f@0
|
178
|
f@0
|
179 trackMenu.add(new JMenuItem(actions.addTrack()));
|
f@0
|
180 trackMenu.add(new JMenuItem(actions.removeSelection()));
|
f@0
|
181 trackMenu.add(new JMenuItem(actions.switchAutomation()));
|
f@0
|
182
|
f@0
|
183 /* -- Haptics Menu -- */
|
f@0
|
184 JMenu hapticsMenu = new JMenu(actions.getVoidAction("haptics"));
|
f@0
|
185 menuBar.add(hapticsMenu);
|
f@0
|
186
|
f@0
|
187 hapticsMenu.add(new JMenuItem(actions.startPhantom()));
|
f@0
|
188 hapticsMenu.add(new JMenuItem(actions.showHaptics()));
|
f@0
|
189 hapticsMenu.add(new JMenuItem(actions.toggleScrub()));
|
f@0
|
190 }
|
f@0
|
191
|
f@0
|
192 protected void initTransportBar(Actions actions){
|
f@0
|
193 /* removes space as a trigger for JButtons when they are focused *
|
f@0
|
194 * this way space can be used to play/stop the current track */
|
f@0
|
195
|
f@0
|
196 /* action for play/stop the current track */
|
f@0
|
197 JComponent contentPane = (JComponent)getContentPane();
|
f@0
|
198 contentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, InputEvent.CTRL_DOWN_MASK), "play");
|
f@0
|
199 contentPane.getActionMap().put("play", actions.play());
|
f@0
|
200 contentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, InputEvent.CTRL_DOWN_MASK), "rew");
|
f@0
|
201 contentPane.getActionMap().put("rew", actions.rew());
|
f@0
|
202
|
f@0
|
203
|
f@0
|
204 /* remove left and right arrow key from transport bar in order not to conflict with the cursor scrubbing */
|
f@0
|
205 transportBar.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "none");
|
f@0
|
206 transportBar.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "none");
|
f@0
|
207 transportBar.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "none");
|
f@0
|
208 transportBar.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "none");
|
f@0
|
209
|
f@0
|
210 /* set up transport bar buttons */
|
f@0
|
211 JToggleButton playButton = new JToggleButton(actions.play());
|
f@0
|
212 playButton.setHideActionText(true);
|
f@0
|
213 playButton.getAccessibleContext().setAccessibleName((String)playButton.getAction().getValue(Action.NAME));
|
f@0
|
214 /* add(Action a) creates a button with the specified action. it is overwritten *
|
f@0
|
215 * in order to add a name to the accessible context - see constructor */
|
f@0
|
216 transportBar.add(playButton);
|
f@0
|
217 transportBar.add(actions.stop());
|
f@0
|
218 transportBar.add(actions.rew());
|
f@0
|
219 transportBar.add(actions.forward());
|
f@0
|
220
|
f@0
|
221 transportBar.add(Box.createRigidArea(new Dimension(20,0)));
|
f@0
|
222 JToggleButton loopButton = new JToggleButton(actions.loop());
|
f@0
|
223 loopButton.setHideActionText(true);
|
f@0
|
224 loopButton.getAccessibleContext().setAccessibleName((String)loopButton.getAction().getValue(Action.NAME));
|
f@0
|
225
|
f@0
|
226 transportBar.add(loopButton);
|
f@0
|
227 }
|
f@0
|
228
|
f@0
|
229 protected void initScrubActions(){
|
f@0
|
230 JComponent contentPane = (JComponent)getContentPane();
|
f@0
|
231
|
f@0
|
232 /* install the keystroke for left and right keys which will be mapperd respectively to scrub left and right */
|
f@0
|
233 contentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT,0), "scrub forw");
|
f@0
|
234 contentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT,0), "scrub backw");
|
f@0
|
235 contentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_F4,0), "scrub play");
|
f@0
|
236 contentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_F4,0,true), "scrub release");
|
f@0
|
237
|
f@0
|
238
|
f@0
|
239 /* install the keystrokes for stopping the scrub all the modifiers are installed as well to prevent *
|
f@0
|
240 * a sequence of actions such as : [press right, press ctrl, release right, release ctrl] to leave the *
|
f@0
|
241 * scrubbing on. This would happen because press right will have no modifiers, whereas release right *
|
f@0
|
242 * would have ctrl modifier and it would not match a simple KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT,0,true) */
|
f@0
|
243 for(int modifier : new int []{
|
f@0
|
244 0, // no modifiers
|
f@0
|
245 InputEvent.SHIFT_DOWN_MASK,
|
f@0
|
246 InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK,
|
f@0
|
247 InputEvent.META_DOWN_MASK,
|
f@0
|
248 InputEvent.ALT_DOWN_MASK,
|
f@0
|
249 InputEvent.ALT_GRAPH_DOWN_MASK,
|
f@0
|
250 InputEvent.CTRL_DOWN_MASK}){
|
f@0
|
251 contentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT,modifier,true), "scrub release");
|
f@0
|
252 contentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT,modifier,true), "scrub release");
|
f@0
|
253 }
|
f@0
|
254
|
f@0
|
255 /* install the actions: scrub left - scrub right - stop scrub release - stop scrub right */
|
f@0
|
256 contentPane.getActionMap().put("scrub backw",actions.scrubAction(Actions.ScrubType.SCRUB_BACKWARDS));
|
f@0
|
257 contentPane.getActionMap().put("scrub forw",actions.scrubAction(Actions.ScrubType.SCRUB_FORWARDS));
|
f@0
|
258 contentPane.getActionMap().put("scrub release" ,actions.scrubAction(Actions.ScrubType.STOP_SCRUB));
|
f@0
|
259 contentPane.getActionMap().put("scrub play" ,actions.scrubAction(Actions.ScrubType.PLAY_SCRUB));
|
f@0
|
260
|
f@0
|
261 }
|
f@0
|
262
|
f@0
|
263 @Override
|
f@0
|
264 public JPanel getContentPane(){
|
f@0
|
265 return (JPanel)super.getContentPane();
|
f@0
|
266 }
|
f@0
|
267
|
f@0
|
268 public ArrangeWindow getArrangeWindow(){
|
f@0
|
269 return arrangeWindow;
|
f@0
|
270 }
|
f@0
|
271
|
f@0
|
272 public JToolBar getTransportBar(){
|
f@0
|
273 return transportBar;
|
f@0
|
274 }
|
f@0
|
275
|
f@0
|
276 public Actions getActions(){
|
f@0
|
277 return actions;
|
f@0
|
278 }
|
f@0
|
279
|
f@0
|
280 }
|