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@33
|
100 menu.addCommandItem(&commandManager_, kCommandClearPreset);
|
andrewm@0
|
101 menu.addSeparator();
|
andrewm@0
|
102 menu.addCommandItem(&commandManager_, kCommandOpenPreset);
|
andrewm@0
|
103 menu.addCommandItem(&commandManager_, kCommandSavePreset);
|
andrewm@0
|
104 #ifndef JUCE_MAC
|
andrewm@0
|
105 menu.addSeparator();
|
andrewm@0
|
106 menu.addCommandItem(&commandManager_, StandardApplicationCommandIDs::quit);
|
andrewm@0
|
107 #endif
|
andrewm@0
|
108 }
|
andrewm@0
|
109 else if(menuIndex == 1) { // Edit
|
andrewm@0
|
110 menu.addCommandItem(&commandManager_, StandardApplicationCommandIDs::undo);
|
andrewm@0
|
111 menu.addCommandItem(&commandManager_, StandardApplicationCommandIDs::redo);
|
andrewm@0
|
112 menu.addSeparator();
|
andrewm@0
|
113 menu.addCommandItem(&commandManager_, StandardApplicationCommandIDs::cut);
|
andrewm@0
|
114 menu.addCommandItem(&commandManager_, StandardApplicationCommandIDs::copy);
|
andrewm@0
|
115 menu.addCommandItem(&commandManager_, StandardApplicationCommandIDs::paste);
|
andrewm@0
|
116 menu.addCommandItem(&commandManager_, StandardApplicationCommandIDs::del);
|
andrewm@0
|
117 menu.addSeparator();
|
andrewm@0
|
118 menu.addCommandItem(&commandManager_, StandardApplicationCommandIDs::selectAll);
|
andrewm@0
|
119 }
|
andrewm@0
|
120 else if(menuIndex == 2) { // Control
|
andrewm@0
|
121 menu.addCommandItem(&commandManager_, kCommandRescanDevices);
|
andrewm@0
|
122 menu.addSeparator();
|
andrewm@31
|
123 menu.addCommandItem(&commandManager_, kCommandLoggingStartStop);
|
andrewm@31
|
124 menu.addCommandItem(&commandManager_, kCommandLoggingPlay);
|
andrewm@31
|
125 menu.addSeparator();
|
andrewm@0
|
126 menu.addCommandItem(&commandManager_, kCommandEnableExperimentalMappings);
|
andrewm@17
|
127 #ifdef ENABLE_TOUCHKEYS_SENSOR_TEST
|
andrewm@17
|
128 menu.addCommandItem(&commandManager_, kCommandTestTouchkeySensors);
|
andrewm@17
|
129 #endif
|
andrewm@0
|
130 }
|
andrewm@0
|
131 else if(menuIndex == 3) { // Window
|
andrewm@0
|
132 menu.addCommandItem(&commandManager_, kCommandShowControlWindow);
|
andrewm@0
|
133 menu.addCommandItem(&commandManager_, kCommandShowKeyboardWindow);
|
andrewm@0
|
134 }
|
andrewm@0
|
135
|
andrewm@0
|
136 return menu;
|
andrewm@0
|
137 }
|
andrewm@0
|
138
|
andrewm@0
|
139 void MainWindow::menuItemSelected(int menuItemID, int topLevelMenuIndex) {
|
andrewm@0
|
140 // TODO
|
andrewm@0
|
141 }
|
andrewm@0
|
142
|
andrewm@0
|
143 // **** Command Manager methods *****
|
andrewm@0
|
144
|
andrewm@0
|
145 ApplicationCommandTarget* MainWindow::getNextCommandTarget() {
|
andrewm@0
|
146 return findFirstTargetParentComponent();
|
andrewm@0
|
147 }
|
andrewm@0
|
148
|
andrewm@0
|
149 // this returns the set of all commands that this target can perform..
|
andrewm@0
|
150 void MainWindow::getAllCommands(Array <CommandID>& commands) {
|
andrewm@0
|
151 // this returns the set of all commands that this target can perform..
|
andrewm@0
|
152 const CommandID ids[] = {
|
andrewm@0
|
153 // File
|
andrewm@33
|
154 kCommandClearPreset,
|
andrewm@33
|
155 kCommandOpenPreset,
|
andrewm@33
|
156 kCommandSavePreset,
|
andrewm@0
|
157 // Edit
|
andrewm@0
|
158 StandardApplicationCommandIDs::undo,
|
andrewm@0
|
159 StandardApplicationCommandIDs::redo,
|
andrewm@0
|
160 StandardApplicationCommandIDs::cut,
|
andrewm@0
|
161 StandardApplicationCommandIDs::copy,
|
andrewm@0
|
162 StandardApplicationCommandIDs::paste,
|
andrewm@0
|
163 StandardApplicationCommandIDs::del,
|
andrewm@0
|
164 StandardApplicationCommandIDs::selectAll,
|
andrewm@0
|
165 // Control
|
andrewm@0
|
166 kCommandRescanDevices,
|
andrewm@31
|
167 kCommandLoggingStartStop,
|
andrewm@31
|
168 kCommandLoggingPlay,
|
andrewm@0
|
169 kCommandEnableExperimentalMappings,
|
andrewm@17
|
170 #ifdef ENABLE_TOUCHKEYS_SENSOR_TEST
|
andrewm@17
|
171 kCommandTestTouchkeySensors,
|
andrewm@17
|
172 #endif
|
andrewm@0
|
173 // Window
|
andrewm@0
|
174 kCommandShowControlWindow,
|
andrewm@0
|
175 kCommandShowKeyboardWindow
|
andrewm@0
|
176 };
|
andrewm@0
|
177
|
andrewm@0
|
178 commands.addArray (ids, numElementsInArray(ids));
|
andrewm@0
|
179 }
|
andrewm@0
|
180
|
andrewm@0
|
181 // This method is used when something needs to find out the details about one of the commands
|
andrewm@0
|
182 // that this object can perform..
|
andrewm@0
|
183 void MainWindow::getCommandInfo(CommandID commandID, ApplicationCommandInfo& result) {
|
andrewm@0
|
184 const String presetsCategory("Presets");
|
andrewm@0
|
185 const String editsCategory("Editing");
|
andrewm@0
|
186 const String controlCategory("Control");
|
andrewm@0
|
187 const String windowCategory("Window");
|
andrewm@0
|
188
|
andrewm@0
|
189 switch (commandID) {
|
andrewm@0
|
190
|
andrewm@0
|
191 // *** File Menu ***
|
andrewm@33
|
192 case kCommandClearPreset:
|
andrewm@33
|
193 result.setInfo("Clear Settings", "Clears the current settings", presetsCategory, 0);
|
andrewm@0
|
194 result.setTicked(false);
|
andrewm@0
|
195 result.setActive(false);
|
andrewm@0
|
196 break;
|
andrewm@0
|
197 case kCommandOpenPreset:
|
andrewm@0
|
198 result.setInfo("Open Preset...", "Opens an existing preset", presetsCategory, 0);
|
andrewm@0
|
199 result.setTicked(false);
|
andrewm@33
|
200 result.setActive(true);
|
andrewm@0
|
201 result.addDefaultKeypress ('O', ModifierKeys::commandModifier);
|
andrewm@0
|
202 break;
|
andrewm@0
|
203 case kCommandSavePreset:
|
andrewm@33
|
204 result.setInfo("Save Preset...", "Saves the current preset", presetsCategory, 0);
|
andrewm@0
|
205 result.setTicked(false);
|
andrewm@33
|
206 result.setActive(true);
|
andrewm@0
|
207 result.addDefaultKeypress ('S', ModifierKeys::commandModifier);
|
andrewm@0
|
208 break;
|
andrewm@0
|
209 // Quit command is handled by JuceApplication
|
andrewm@0
|
210
|
andrewm@0
|
211 // *** Edit Menu ***
|
andrewm@0
|
212 case StandardApplicationCommandIDs::undo:
|
andrewm@0
|
213 result.setInfo("Undo", "Undo", editsCategory, 0);
|
andrewm@0
|
214 result.setTicked(false);
|
andrewm@0
|
215 result.setActive(false);
|
andrewm@0
|
216 result.addDefaultKeypress ('Z', ModifierKeys::commandModifier);
|
andrewm@0
|
217 break;
|
andrewm@0
|
218 case StandardApplicationCommandIDs::redo:
|
andrewm@0
|
219 result.setInfo("Redo", "Redo", editsCategory, 0);
|
andrewm@0
|
220 result.setTicked(false);
|
andrewm@0
|
221 result.setActive(false);
|
andrewm@0
|
222 result.addDefaultKeypress ('Z', ModifierKeys::commandModifier | ModifierKeys::shiftModifier);
|
andrewm@0
|
223 break;
|
andrewm@0
|
224 case StandardApplicationCommandIDs::cut:
|
andrewm@0
|
225 result.setInfo("Cut", "Cut", editsCategory, 0);
|
andrewm@0
|
226 result.setTicked(false);
|
andrewm@0
|
227 result.setActive(false);
|
andrewm@0
|
228 result.addDefaultKeypress ('X', ModifierKeys::commandModifier);
|
andrewm@0
|
229 break;
|
andrewm@0
|
230 case StandardApplicationCommandIDs::copy:
|
andrewm@0
|
231 result.setInfo("Copy", "Copy", editsCategory, 0);
|
andrewm@0
|
232 result.setTicked(false);
|
andrewm@0
|
233 result.setActive(false);
|
andrewm@0
|
234 result.addDefaultKeypress ('C', ModifierKeys::commandModifier);
|
andrewm@0
|
235 break;
|
andrewm@0
|
236 case StandardApplicationCommandIDs::paste:
|
andrewm@0
|
237 result.setInfo("Paste", "Paste", editsCategory, 0);
|
andrewm@0
|
238 result.setTicked(false);
|
andrewm@0
|
239 result.setActive(false);
|
andrewm@0
|
240 result.addDefaultKeypress ('V', ModifierKeys::commandModifier);
|
andrewm@0
|
241 break;
|
andrewm@0
|
242 case StandardApplicationCommandIDs::del:
|
andrewm@0
|
243 result.setInfo("Delete", "Delete", editsCategory, 0);
|
andrewm@0
|
244 result.setTicked(false);
|
andrewm@0
|
245 result.setActive(false);
|
andrewm@0
|
246 break;
|
andrewm@0
|
247 case StandardApplicationCommandIDs::selectAll:
|
andrewm@0
|
248 result.setInfo("Select All", "Select All", editsCategory, 0);
|
andrewm@0
|
249 result.setTicked(false);
|
andrewm@0
|
250 result.setActive(false);
|
andrewm@0
|
251 result.addDefaultKeypress ('A', ModifierKeys::commandModifier);
|
andrewm@0
|
252 break;
|
andrewm@0
|
253
|
andrewm@0
|
254 // *** Control Menu ***
|
andrewm@0
|
255 case kCommandRescanDevices:
|
andrewm@0
|
256 result.setInfo("Rescan Devices", "Rescans available TouchKeys and MIDI devices", controlCategory, 0);
|
andrewm@0
|
257 result.setTicked(false);
|
andrewm@28
|
258 result.setActive(true);
|
andrewm@0
|
259 result.addDefaultKeypress ('R', ModifierKeys::commandModifier);
|
andrewm@0
|
260 break;
|
andrewm@31
|
261 case kCommandLoggingStartStop:
|
andrewm@31
|
262 result.setInfo("Record Log File", "Records TouchKeys and MIDI data to file", controlCategory, 0);
|
andrewm@31
|
263 result.setTicked(controller_.isLogging());
|
andrewm@31
|
264 result.setActive(true);
|
andrewm@31
|
265 break;
|
andrewm@31
|
266 case kCommandLoggingPlay:
|
andrewm@31
|
267 result.setInfo("Play Log...", "Plays TouchKeys and MIDI from file", controlCategory, 0);
|
andrewm@31
|
268 result.setTicked(false);
|
andrewm@31
|
269 result.setActive(false);
|
andrewm@31
|
270 break;
|
andrewm@0
|
271 case kCommandEnableExperimentalMappings:
|
andrewm@0
|
272 result.setInfo("Enable Experimental Mappings", "Enables mappings which are still experimental", controlCategory, 0);
|
andrewm@0
|
273 result.setTicked(controller_.experimentalMappingsEnabled());
|
andrewm@0
|
274 break;
|
andrewm@17
|
275 #ifdef ENABLE_TOUCHKEYS_SENSOR_TEST
|
andrewm@17
|
276 case kCommandTestTouchkeySensors:
|
andrewm@17
|
277 result.setInfo("Test TouchKeys Sensors", "Enables a test of individual TouchKeys sensors", controlCategory, 0);
|
andrewm@17
|
278 result.setActive(controller_.availableTouchkeyDevices().size() > 0);
|
andrewm@17
|
279 result.setTicked(controller_.touchkeySensorTestIsRunning());
|
andrewm@17
|
280 break;
|
andrewm@17
|
281 #endif
|
andrewm@0
|
282
|
andrewm@0
|
283 // *** Window Menu ***
|
andrewm@0
|
284 case kCommandShowControlWindow:
|
andrewm@0
|
285 result.setInfo("TouchKeys Controls", "Show control and mapping window", windowCategory, 0);
|
andrewm@0
|
286 result.setTicked(false);
|
andrewm@12
|
287 result.addDefaultKeypress ('1', ModifierKeys::commandModifier);
|
andrewm@0
|
288 break;
|
andrewm@0
|
289 case kCommandShowKeyboardWindow:
|
andrewm@0
|
290 result.setInfo("Keyboard Display", "Show keyboard display", windowCategory, 0);
|
andrewm@0
|
291 result.setTicked(false);
|
andrewm@12
|
292 result.addDefaultKeypress ('2', ModifierKeys::commandModifier);
|
andrewm@0
|
293 break;
|
andrewm@0
|
294
|
andrewm@0
|
295 default:
|
andrewm@0
|
296 break;
|
andrewm@0
|
297 };
|
andrewm@0
|
298 }
|
andrewm@0
|
299
|
andrewm@0
|
300 bool MainWindow::perform(const InvocationInfo& info) {
|
andrewm@0
|
301 switch (info.commandID)
|
andrewm@0
|
302 {
|
andrewm@33
|
303 case kCommandClearPreset:
|
andrewm@33
|
304 break;
|
andrewm@33
|
305 case kCommandOpenPreset:
|
andrewm@33
|
306 controller_.loadPresetWithDialog();
|
andrewm@33
|
307 break;
|
andrewm@33
|
308 case kCommandSavePreset:
|
andrewm@33
|
309 controller_.savePresetWithDialog();
|
andrewm@0
|
310 break;
|
andrewm@0
|
311 case kCommandRescanDevices:
|
andrewm@28
|
312 controller_.tellDevicesToUpdate();
|
andrewm@0
|
313 break;
|
andrewm@31
|
314 case kCommandLoggingStartStop:
|
andrewm@31
|
315 if(controller_.isLogging())
|
andrewm@31
|
316 controller_.stopLogging();
|
andrewm@31
|
317 else
|
andrewm@31
|
318 controller_.startLogging();
|
andrewm@31
|
319 break;
|
andrewm@31
|
320 case kCommandLoggingPlay:
|
andrewm@31
|
321 // TODO
|
andrewm@31
|
322 break;
|
andrewm@0
|
323 case kCommandEnableExperimentalMappings:
|
andrewm@0
|
324 controller_.setExperimentalMappingsEnabled(!controller_.experimentalMappingsEnabled());
|
andrewm@0
|
325 break;
|
andrewm@17
|
326 #ifdef ENABLE_TOUCHKEYS_SENSOR_TEST
|
andrewm@17
|
327 case kCommandTestTouchkeySensors:
|
andrewm@17
|
328 if(!controller_.touchkeySensorTestIsRunning())
|
andrewm@17
|
329 controller_.touchkeySensorTestStart(mainComponent_.currentTouchkeysSelectedPath().toUTF8(), controller_.touchkeyDeviceLowestMidiNote());
|
andrewm@17
|
330 else
|
andrewm@17
|
331 controller_.touchkeySensorTestStop();
|
andrewm@17
|
332 break;
|
andrewm@17
|
333 #endif
|
andrewm@0
|
334 case kCommandShowControlWindow:
|
andrewm@0
|
335 toFront(true);
|
andrewm@0
|
336 break;
|
andrewm@0
|
337 case kCommandShowKeyboardWindow:
|
andrewm@0
|
338 controller_.showKeyboardDisplayWindow();
|
andrewm@0
|
339 break;
|
andrewm@0
|
340
|
andrewm@0
|
341 default:
|
andrewm@0
|
342 return false;
|
andrewm@0
|
343 };
|
andrewm@0
|
344
|
andrewm@0
|
345 return true;
|
andrewm@0
|
346 }
|