andrewm@0
|
1 /*
|
andrewm@0
|
2 TouchKeys: multi-touch musical keyboard control software
|
andrewm@0
|
3 Copyright (c) 2013 Andrew McPherson
|
andrewm@0
|
4
|
andrewm@0
|
5 This program is free software: you can redistribute it and/or modify
|
andrewm@0
|
6 it under the terms of the GNU General Public License as published by
|
andrewm@0
|
7 the Free Software Foundation, either version 3 of the License, or
|
andrewm@0
|
8 (at your option) any later version.
|
andrewm@0
|
9
|
andrewm@0
|
10 This program is distributed in the hope that it will be useful,
|
andrewm@0
|
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
andrewm@0
|
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
andrewm@0
|
13 GNU General Public License for more details.
|
andrewm@0
|
14
|
andrewm@0
|
15 You should have received a copy of the GNU General Public License
|
andrewm@0
|
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
|
andrewm@0
|
17
|
andrewm@0
|
18 =====================================================================
|
andrewm@0
|
19
|
andrewm@0
|
20 MainWindow.cpp: the control window, plus menu bar and Juce application methods
|
andrewm@0
|
21 */
|
andrewm@0
|
22
|
andrewm@0
|
23 #include "../../JuceLibraryCode/JuceHeader.h"
|
andrewm@0
|
24 #include "MainWindow.h"
|
andrewm@0
|
25
|
andrewm@0
|
26 //==============================================================================
|
andrewm@0
|
27 MainWindow::MainWindow(MainApplicationController& controller)
|
andrewm@0
|
28 : DocumentWindow ("TouchKeys", Colours::lightgrey, DocumentWindow::allButtons),
|
andrewm@0
|
29 controller_(controller)
|
andrewm@0
|
30 {
|
andrewm@0
|
31 commandManager_.registerAllCommandsForTarget(this);
|
andrewm@0
|
32 commandManager_.registerAllCommandsForTarget(JUCEApplication::getInstance());
|
andrewm@0
|
33
|
andrewm@0
|
34 // This lets the command manager use keypresses that arrive in our window to send
|
andrewm@0
|
35 // out commands
|
andrewm@0
|
36 addKeyListener(commandManager_.getKeyMappings());
|
andrewm@0
|
37
|
andrewm@0
|
38 // Create the menu bar, either in the window or at the top of the screen
|
andrewm@0
|
39 #if JUCE_MAC
|
andrewm@0
|
40 MenuBarModel::setMacMainMenu(this);
|
andrewm@0
|
41 #else
|
andrewm@0
|
42 // Menu bar goes at the top of the window
|
andrewm@0
|
43 setMenuBar(this);
|
andrewm@0
|
44
|
andrewm@0
|
45 // Window height should change to accommodate it
|
andrewm@0
|
46 Component *actualMenuBar = getMenuBarComponent();
|
andrewm@0
|
47 if(actualMenuBar != 0) {
|
andrewm@20
|
48 juce::Rectangle<int> r = actualMenuBar->getBounds();
|
andrewm@0
|
49 setSize(getWidth(), getHeight() + r.getHeight());
|
andrewm@0
|
50 }
|
andrewm@0
|
51 #endif /* JUCE_MAC */
|
andrewm@0
|
52
|
andrewm@0
|
53 // Tells our menu bar model that it should watch this command manager for
|
andrewm@0
|
54 // changes, and send change messages accordingly.
|
andrewm@0
|
55 setApplicationCommandManagerToWatch(&commandManager_);
|
andrewm@0
|
56
|
andrewm@0
|
57 mainComponent_.setMainApplicationController(&controller_);
|
andrewm@0
|
58 setContentNonOwned(&mainComponent_, true);
|
andrewm@0
|
59
|
andrewm@0
|
60 commandManager_.setFirstCommandTarget(this);
|
andrewm@0
|
61
|
andrewm@0
|
62 // Start a timer that will keep the interface in sync with the application
|
andrewm@0
|
63 startTimer(50);
|
andrewm@0
|
64
|
andrewm@0
|
65 centreWithSize (getWidth(), getHeight());
|
andrewm@0
|
66 setUsingNativeTitleBar(true);
|
andrewm@31
|
67
|
andrewm@31
|
68 // Allow resizing to be larger vertically
|
andrewm@31
|
69 setResizable(true, true);
|
andrewm@31
|
70 setResizeLimits(getWidth(), getHeight(), getWidth(), 2048);
|
andrewm@31
|
71
|
andrewm@0
|
72 setVisible (true);
|
andrewm@0
|
73 }
|
andrewm@0
|
74
|
andrewm@0
|
75 MainWindow::~MainWindow() {
|
andrewm@0
|
76 // Delete the menu bar before exiting
|
andrewm@0
|
77 #if JUCE_MAC
|
andrewm@0
|
78 MenuBarModel::setMacMainMenu(nullptr);
|
andrewm@0
|
79 #else
|
andrewm@0
|
80 setMenuBar(nullptr);
|
andrewm@0
|
81 #endif /* JUCE_MAC */
|
andrewm@0
|
82 }
|
andrewm@0
|
83
|
andrewm@0
|
84 // Handle periodic GUI updates, keeping the GUI in sync with the underlying system
|
andrewm@0
|
85 void MainWindow::timerCallback() {
|
andrewm@0
|
86 mainComponent_.synchronize();
|
andrewm@0
|
87 }
|
andrewm@0
|
88
|
andrewm@0
|
89 // ***** Juce menu bar methods ****
|
andrewm@0
|
90 StringArray MainWindow::getMenuBarNames() {
|
andrewm@0
|
91 const char* const names[] = { "File", "Edit", "Control", "Window", nullptr };
|
andrewm@0
|
92
|
andrewm@0
|
93 return StringArray (names);
|
andrewm@0
|
94 }
|
andrewm@0
|
95
|
andrewm@0
|
96 PopupMenu MainWindow::getMenuForIndex(int menuIndex, const String& menuName) {
|
andrewm@0
|
97 PopupMenu menu;
|
andrewm@0
|
98
|
andrewm@0
|
99 if(menuIndex == 0) { // File
|
andrewm@0
|
100 menu.addCommandItem(&commandManager_, kCommandNewPreset);
|
andrewm@0
|
101 menu.addSeparator();
|
andrewm@0
|
102 menu.addCommandItem(&commandManager_, kCommandOpenPreset);
|
andrewm@0
|
103 menu.addSeparator();
|
andrewm@0
|
104 menu.addCommandItem(&commandManager_, kCommandSavePreset);
|
andrewm@0
|
105 menu.addCommandItem(&commandManager_, kCommandSavePresetAs);
|
andrewm@0
|
106 #ifndef JUCE_MAC
|
andrewm@0
|
107 menu.addSeparator();
|
andrewm@0
|
108 menu.addCommandItem(&commandManager_, StandardApplicationCommandIDs::quit);
|
andrewm@0
|
109 #endif
|
andrewm@0
|
110 }
|
andrewm@0
|
111 else if(menuIndex == 1) { // Edit
|
andrewm@0
|
112 menu.addCommandItem(&commandManager_, StandardApplicationCommandIDs::undo);
|
andrewm@0
|
113 menu.addCommandItem(&commandManager_, StandardApplicationCommandIDs::redo);
|
andrewm@0
|
114 menu.addSeparator();
|
andrewm@0
|
115 menu.addCommandItem(&commandManager_, StandardApplicationCommandIDs::cut);
|
andrewm@0
|
116 menu.addCommandItem(&commandManager_, StandardApplicationCommandIDs::copy);
|
andrewm@0
|
117 menu.addCommandItem(&commandManager_, StandardApplicationCommandIDs::paste);
|
andrewm@0
|
118 menu.addCommandItem(&commandManager_, StandardApplicationCommandIDs::del);
|
andrewm@0
|
119 menu.addSeparator();
|
andrewm@0
|
120 menu.addCommandItem(&commandManager_, StandardApplicationCommandIDs::selectAll);
|
andrewm@0
|
121 }
|
andrewm@0
|
122 else if(menuIndex == 2) { // Control
|
andrewm@0
|
123 menu.addCommandItem(&commandManager_, kCommandRescanDevices);
|
andrewm@0
|
124 menu.addSeparator();
|
andrewm@31
|
125 menu.addCommandItem(&commandManager_, kCommandLoggingStartStop);
|
andrewm@31
|
126 menu.addCommandItem(&commandManager_, kCommandLoggingPlay);
|
andrewm@31
|
127 menu.addSeparator();
|
andrewm@0
|
128 menu.addCommandItem(&commandManager_, kCommandEnableExperimentalMappings);
|
andrewm@17
|
129 #ifdef ENABLE_TOUCHKEYS_SENSOR_TEST
|
andrewm@17
|
130 menu.addCommandItem(&commandManager_, kCommandTestTouchkeySensors);
|
andrewm@17
|
131 #endif
|
andrewm@0
|
132 }
|
andrewm@0
|
133 else if(menuIndex == 3) { // Window
|
andrewm@0
|
134 menu.addCommandItem(&commandManager_, kCommandShowControlWindow);
|
andrewm@0
|
135 menu.addCommandItem(&commandManager_, kCommandShowKeyboardWindow);
|
andrewm@0
|
136 }
|
andrewm@0
|
137
|
andrewm@0
|
138 return menu;
|
andrewm@0
|
139 }
|
andrewm@0
|
140
|
andrewm@0
|
141 void MainWindow::menuItemSelected(int menuItemID, int topLevelMenuIndex) {
|
andrewm@0
|
142 // TODO
|
andrewm@0
|
143 }
|
andrewm@0
|
144
|
andrewm@0
|
145 // **** Command Manager methods *****
|
andrewm@0
|
146
|
andrewm@0
|
147 ApplicationCommandTarget* MainWindow::getNextCommandTarget() {
|
andrewm@0
|
148 return findFirstTargetParentComponent();
|
andrewm@0
|
149 }
|
andrewm@0
|
150
|
andrewm@0
|
151 // this returns the set of all commands that this target can perform..
|
andrewm@0
|
152 void MainWindow::getAllCommands(Array <CommandID>& commands) {
|
andrewm@0
|
153 // this returns the set of all commands that this target can perform..
|
andrewm@0
|
154 const CommandID ids[] = {
|
andrewm@0
|
155 // File
|
andrewm@0
|
156 kCommandNewPreset, kCommandOpenPreset, kCommandSavePreset,
|
andrewm@0
|
157 kCommandSavePresetAs,
|
andrewm@0
|
158 // Edit
|
andrewm@0
|
159 StandardApplicationCommandIDs::undo,
|
andrewm@0
|
160 StandardApplicationCommandIDs::redo,
|
andrewm@0
|
161 StandardApplicationCommandIDs::cut,
|
andrewm@0
|
162 StandardApplicationCommandIDs::copy,
|
andrewm@0
|
163 StandardApplicationCommandIDs::paste,
|
andrewm@0
|
164 StandardApplicationCommandIDs::del,
|
andrewm@0
|
165 StandardApplicationCommandIDs::selectAll,
|
andrewm@0
|
166 // Control
|
andrewm@0
|
167 kCommandRescanDevices,
|
andrewm@31
|
168 kCommandLoggingStartStop,
|
andrewm@31
|
169 kCommandLoggingPlay,
|
andrewm@0
|
170 kCommandEnableExperimentalMappings,
|
andrewm@17
|
171 #ifdef ENABLE_TOUCHKEYS_SENSOR_TEST
|
andrewm@17
|
172 kCommandTestTouchkeySensors,
|
andrewm@17
|
173 #endif
|
andrewm@0
|
174 // Window
|
andrewm@0
|
175 kCommandShowControlWindow,
|
andrewm@0
|
176 kCommandShowKeyboardWindow
|
andrewm@0
|
177 };
|
andrewm@0
|
178
|
andrewm@0
|
179 commands.addArray (ids, numElementsInArray(ids));
|
andrewm@0
|
180 }
|
andrewm@0
|
181
|
andrewm@0
|
182 // This method is used when something needs to find out the details about one of the commands
|
andrewm@0
|
183 // that this object can perform..
|
andrewm@0
|
184 void MainWindow::getCommandInfo(CommandID commandID, ApplicationCommandInfo& result) {
|
andrewm@0
|
185 const String presetsCategory("Presets");
|
andrewm@0
|
186 const String editsCategory("Editing");
|
andrewm@0
|
187 const String controlCategory("Control");
|
andrewm@0
|
188 const String windowCategory("Window");
|
andrewm@0
|
189
|
andrewm@0
|
190 switch (commandID) {
|
andrewm@0
|
191
|
andrewm@0
|
192 // *** File Menu ***
|
andrewm@0
|
193 case kCommandNewPreset:
|
andrewm@0
|
194 result.setInfo("New Preset", "Clears the current settings", presetsCategory, 0);
|
andrewm@0
|
195 result.setTicked(false);
|
andrewm@0
|
196 result.setActive(false);
|
andrewm@0
|
197 result.addDefaultKeypress ('N', ModifierKeys::commandModifier);
|
andrewm@0
|
198 break;
|
andrewm@0
|
199 case kCommandOpenPreset:
|
andrewm@0
|
200 result.setInfo("Open Preset...", "Opens an existing preset", presetsCategory, 0);
|
andrewm@0
|
201 result.setTicked(false);
|
andrewm@0
|
202 result.setActive(false);
|
andrewm@0
|
203 result.addDefaultKeypress ('O', ModifierKeys::commandModifier);
|
andrewm@0
|
204 break;
|
andrewm@0
|
205 case kCommandSavePreset:
|
andrewm@0
|
206 result.setInfo("Save Preset", "Saves the current preset", presetsCategory, 0);
|
andrewm@0
|
207 result.setTicked(false);
|
andrewm@0
|
208 result.setActive(false);
|
andrewm@0
|
209 result.addDefaultKeypress ('S', ModifierKeys::commandModifier);
|
andrewm@0
|
210 break;
|
andrewm@0
|
211 case kCommandSavePresetAs:
|
andrewm@0
|
212 result.setInfo("Save Preset As...", "Saves the current preset with a new name", presetsCategory, 0);
|
andrewm@0
|
213 result.setTicked (false);
|
andrewm@0
|
214 result.setActive(false);
|
andrewm@0
|
215 break;
|
andrewm@0
|
216 // Quit command is handled by JuceApplication
|
andrewm@0
|
217
|
andrewm@0
|
218 // *** Edit Menu ***
|
andrewm@0
|
219 case StandardApplicationCommandIDs::undo:
|
andrewm@0
|
220 result.setInfo("Undo", "Undo", editsCategory, 0);
|
andrewm@0
|
221 result.setTicked(false);
|
andrewm@0
|
222 result.setActive(false);
|
andrewm@0
|
223 result.addDefaultKeypress ('Z', ModifierKeys::commandModifier);
|
andrewm@0
|
224 break;
|
andrewm@0
|
225 case StandardApplicationCommandIDs::redo:
|
andrewm@0
|
226 result.setInfo("Redo", "Redo", editsCategory, 0);
|
andrewm@0
|
227 result.setTicked(false);
|
andrewm@0
|
228 result.setActive(false);
|
andrewm@0
|
229 result.addDefaultKeypress ('Z', ModifierKeys::commandModifier | ModifierKeys::shiftModifier);
|
andrewm@0
|
230 break;
|
andrewm@0
|
231 case StandardApplicationCommandIDs::cut:
|
andrewm@0
|
232 result.setInfo("Cut", "Cut", editsCategory, 0);
|
andrewm@0
|
233 result.setTicked(false);
|
andrewm@0
|
234 result.setActive(false);
|
andrewm@0
|
235 result.addDefaultKeypress ('X', ModifierKeys::commandModifier);
|
andrewm@0
|
236 break;
|
andrewm@0
|
237 case StandardApplicationCommandIDs::copy:
|
andrewm@0
|
238 result.setInfo("Copy", "Copy", editsCategory, 0);
|
andrewm@0
|
239 result.setTicked(false);
|
andrewm@0
|
240 result.setActive(false);
|
andrewm@0
|
241 result.addDefaultKeypress ('C', ModifierKeys::commandModifier);
|
andrewm@0
|
242 break;
|
andrewm@0
|
243 case StandardApplicationCommandIDs::paste:
|
andrewm@0
|
244 result.setInfo("Paste", "Paste", editsCategory, 0);
|
andrewm@0
|
245 result.setTicked(false);
|
andrewm@0
|
246 result.setActive(false);
|
andrewm@0
|
247 result.addDefaultKeypress ('V', ModifierKeys::commandModifier);
|
andrewm@0
|
248 break;
|
andrewm@0
|
249 case StandardApplicationCommandIDs::del:
|
andrewm@0
|
250 result.setInfo("Delete", "Delete", editsCategory, 0);
|
andrewm@0
|
251 result.setTicked(false);
|
andrewm@0
|
252 result.setActive(false);
|
andrewm@0
|
253 break;
|
andrewm@0
|
254 case StandardApplicationCommandIDs::selectAll:
|
andrewm@0
|
255 result.setInfo("Select All", "Select All", editsCategory, 0);
|
andrewm@0
|
256 result.setTicked(false);
|
andrewm@0
|
257 result.setActive(false);
|
andrewm@0
|
258 result.addDefaultKeypress ('A', ModifierKeys::commandModifier);
|
andrewm@0
|
259 break;
|
andrewm@0
|
260
|
andrewm@0
|
261 // *** Control Menu ***
|
andrewm@0
|
262 case kCommandRescanDevices:
|
andrewm@0
|
263 result.setInfo("Rescan Devices", "Rescans available TouchKeys and MIDI devices", controlCategory, 0);
|
andrewm@0
|
264 result.setTicked(false);
|
andrewm@28
|
265 result.setActive(true);
|
andrewm@0
|
266 result.addDefaultKeypress ('R', ModifierKeys::commandModifier);
|
andrewm@0
|
267 break;
|
andrewm@31
|
268 case kCommandLoggingStartStop:
|
andrewm@31
|
269 result.setInfo("Record Log File", "Records TouchKeys and MIDI data to file", controlCategory, 0);
|
andrewm@31
|
270 result.setTicked(controller_.isLogging());
|
andrewm@31
|
271 result.setActive(true);
|
andrewm@31
|
272 break;
|
andrewm@31
|
273 case kCommandLoggingPlay:
|
andrewm@31
|
274 result.setInfo("Play Log...", "Plays TouchKeys and MIDI from file", controlCategory, 0);
|
andrewm@31
|
275 result.setTicked(false);
|
andrewm@31
|
276 result.setActive(false);
|
andrewm@31
|
277 break;
|
andrewm@0
|
278 case kCommandEnableExperimentalMappings:
|
andrewm@0
|
279 result.setInfo("Enable Experimental Mappings", "Enables mappings which are still experimental", controlCategory, 0);
|
andrewm@0
|
280 result.setTicked(controller_.experimentalMappingsEnabled());
|
andrewm@0
|
281 break;
|
andrewm@17
|
282 #ifdef ENABLE_TOUCHKEYS_SENSOR_TEST
|
andrewm@17
|
283 case kCommandTestTouchkeySensors:
|
andrewm@17
|
284 result.setInfo("Test TouchKeys Sensors", "Enables a test of individual TouchKeys sensors", controlCategory, 0);
|
andrewm@17
|
285 result.setActive(controller_.availableTouchkeyDevices().size() > 0);
|
andrewm@17
|
286 result.setTicked(controller_.touchkeySensorTestIsRunning());
|
andrewm@17
|
287 break;
|
andrewm@17
|
288 #endif
|
andrewm@0
|
289
|
andrewm@0
|
290 // *** Window Menu ***
|
andrewm@0
|
291 case kCommandShowControlWindow:
|
andrewm@0
|
292 result.setInfo("TouchKeys Controls", "Show control and mapping window", windowCategory, 0);
|
andrewm@0
|
293 result.setTicked(false);
|
andrewm@12
|
294 result.addDefaultKeypress ('1', ModifierKeys::commandModifier);
|
andrewm@0
|
295 break;
|
andrewm@0
|
296 case kCommandShowKeyboardWindow:
|
andrewm@0
|
297 result.setInfo("Keyboard Display", "Show keyboard display", windowCategory, 0);
|
andrewm@0
|
298 result.setTicked(false);
|
andrewm@12
|
299 result.addDefaultKeypress ('2', ModifierKeys::commandModifier);
|
andrewm@0
|
300 break;
|
andrewm@0
|
301
|
andrewm@0
|
302 default:
|
andrewm@0
|
303 break;
|
andrewm@0
|
304 };
|
andrewm@0
|
305 }
|
andrewm@0
|
306
|
andrewm@0
|
307 bool MainWindow::perform(const InvocationInfo& info) {
|
andrewm@0
|
308 switch (info.commandID)
|
andrewm@0
|
309 {
|
andrewm@0
|
310 case kCommandNewPreset:
|
andrewm@0
|
311 break;
|
andrewm@0
|
312 case kCommandRescanDevices:
|
andrewm@28
|
313 controller_.tellDevicesToUpdate();
|
andrewm@0
|
314 break;
|
andrewm@31
|
315 case kCommandLoggingStartStop:
|
andrewm@31
|
316 if(controller_.isLogging())
|
andrewm@31
|
317 controller_.stopLogging();
|
andrewm@31
|
318 else
|
andrewm@31
|
319 controller_.startLogging();
|
andrewm@31
|
320 break;
|
andrewm@31
|
321 case kCommandLoggingPlay:
|
andrewm@31
|
322 // TODO
|
andrewm@31
|
323 break;
|
andrewm@0
|
324 case kCommandEnableExperimentalMappings:
|
andrewm@0
|
325 controller_.setExperimentalMappingsEnabled(!controller_.experimentalMappingsEnabled());
|
andrewm@0
|
326 break;
|
andrewm@17
|
327 #ifdef ENABLE_TOUCHKEYS_SENSOR_TEST
|
andrewm@17
|
328 case kCommandTestTouchkeySensors:
|
andrewm@17
|
329 if(!controller_.touchkeySensorTestIsRunning())
|
andrewm@17
|
330 controller_.touchkeySensorTestStart(mainComponent_.currentTouchkeysSelectedPath().toUTF8(), controller_.touchkeyDeviceLowestMidiNote());
|
andrewm@17
|
331 else
|
andrewm@17
|
332 controller_.touchkeySensorTestStop();
|
andrewm@17
|
333 break;
|
andrewm@17
|
334 #endif
|
andrewm@0
|
335 case kCommandShowControlWindow:
|
andrewm@0
|
336 toFront(true);
|
andrewm@0
|
337 break;
|
andrewm@0
|
338 case kCommandShowKeyboardWindow:
|
andrewm@0
|
339 controller_.showKeyboardDisplayWindow();
|
andrewm@0
|
340 break;
|
andrewm@0
|
341
|
andrewm@0
|
342 default:
|
andrewm@0
|
343 return false;
|
andrewm@0
|
344 };
|
andrewm@0
|
345
|
andrewm@0
|
346 return true;
|
andrewm@0
|
347 }
|