andrewm@0: /* andrewm@0: TouchKeys: multi-touch musical keyboard control software andrewm@0: Copyright (c) 2013 Andrew McPherson andrewm@0: andrewm@0: This program is free software: you can redistribute it and/or modify andrewm@0: it under the terms of the GNU General Public License as published by andrewm@0: the Free Software Foundation, either version 3 of the License, or andrewm@0: (at your option) any later version. andrewm@0: andrewm@0: This program is distributed in the hope that it will be useful, andrewm@0: but WITHOUT ANY WARRANTY; without even the implied warranty of andrewm@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the andrewm@0: GNU General Public License for more details. andrewm@0: andrewm@0: You should have received a copy of the GNU General Public License andrewm@0: along with this program. If not, see . andrewm@0: andrewm@0: ===================================================================== andrewm@0: andrewm@0: MainWindow.cpp: the control window, plus menu bar and Juce application methods andrewm@0: */ andrewm@0: andrewm@50: #ifndef TOUCHKEYS_NO_GUI andrewm@50: andrewm@0: #include "../../JuceLibraryCode/JuceHeader.h" andrewm@0: #include "MainWindow.h" andrewm@0: andrewm@0: //============================================================================== andrewm@0: MainWindow::MainWindow(MainApplicationController& controller) andrewm@0: : DocumentWindow ("TouchKeys", Colours::lightgrey, DocumentWindow::allButtons), andrewm@0: controller_(controller) andrewm@0: { andrewm@0: commandManager_.registerAllCommandsForTarget(this); andrewm@0: commandManager_.registerAllCommandsForTarget(JUCEApplication::getInstance()); andrewm@0: andrewm@0: // This lets the command manager use keypresses that arrive in our window to send andrewm@0: // out commands andrewm@0: addKeyListener(commandManager_.getKeyMappings()); andrewm@0: andrewm@0: // Create the menu bar, either in the window or at the top of the screen andrewm@0: #if JUCE_MAC andrewm@0: MenuBarModel::setMacMainMenu(this); andrewm@0: #else andrewm@0: // Menu bar goes at the top of the window andrewm@0: setMenuBar(this); andrewm@0: andrewm@0: // Window height should change to accommodate it andrewm@0: Component *actualMenuBar = getMenuBarComponent(); andrewm@0: if(actualMenuBar != 0) { andrewm@20: juce::Rectangle r = actualMenuBar->getBounds(); andrewm@0: setSize(getWidth(), getHeight() + r.getHeight()); andrewm@0: } andrewm@0: #endif /* JUCE_MAC */ andrewm@0: andrewm@0: // Tells our menu bar model that it should watch this command manager for andrewm@0: // changes, and send change messages accordingly. andrewm@0: setApplicationCommandManagerToWatch(&commandManager_); andrewm@0: andrewm@0: mainComponent_.setMainApplicationController(&controller_); andrewm@0: setContentNonOwned(&mainComponent_, true); andrewm@0: andrewm@0: commandManager_.setFirstCommandTarget(this); andrewm@0: andrewm@0: // Start a timer that will keep the interface in sync with the application andrewm@0: startTimer(50); andrewm@0: andrewm@0: centreWithSize (getWidth(), getHeight()); andrewm@0: setUsingNativeTitleBar(true); andrewm@31: andrewm@31: // Allow resizing to be larger vertically andrewm@31: setResizable(true, true); andrewm@31: setResizeLimits(getWidth(), getHeight(), getWidth(), 2048); andrewm@31: andrewm@0: setVisible (true); andrewm@0: } andrewm@0: andrewm@0: MainWindow::~MainWindow() { andrewm@0: // Delete the menu bar before exiting andrewm@0: #if JUCE_MAC andrewm@0: MenuBarModel::setMacMainMenu(nullptr); andrewm@0: #else andrewm@0: setMenuBar(nullptr); andrewm@0: #endif /* JUCE_MAC */ andrewm@0: } andrewm@0: andrewm@0: // Handle periodic GUI updates, keeping the GUI in sync with the underlying system andrewm@0: void MainWindow::timerCallback() { andrewm@0: mainComponent_.synchronize(); andrewm@0: } andrewm@0: andrewm@0: // ***** Juce menu bar methods **** andrewm@0: StringArray MainWindow::getMenuBarNames() { andrewm@0: const char* const names[] = { "File", "Edit", "Control", "Window", nullptr }; andrewm@0: andrewm@0: return StringArray (names); andrewm@0: } andrewm@0: andrewm@0: PopupMenu MainWindow::getMenuForIndex(int menuIndex, const String& menuName) { andrewm@0: PopupMenu menu; andrewm@0: andrewm@0: if(menuIndex == 0) { // File andrewm@33: menu.addCommandItem(&commandManager_, kCommandClearPreset); andrewm@0: menu.addSeparator(); andrewm@0: menu.addCommandItem(&commandManager_, kCommandOpenPreset); andrewm@0: menu.addCommandItem(&commandManager_, kCommandSavePreset); andrewm@0: #ifndef JUCE_MAC andrewm@0: menu.addSeparator(); andrewm@0: menu.addCommandItem(&commandManager_, StandardApplicationCommandIDs::quit); andrewm@0: #endif andrewm@0: } andrewm@0: else if(menuIndex == 1) { // Edit andrewm@0: menu.addCommandItem(&commandManager_, StandardApplicationCommandIDs::undo); andrewm@0: menu.addCommandItem(&commandManager_, StandardApplicationCommandIDs::redo); andrewm@0: menu.addSeparator(); andrewm@0: menu.addCommandItem(&commandManager_, StandardApplicationCommandIDs::cut); andrewm@0: menu.addCommandItem(&commandManager_, StandardApplicationCommandIDs::copy); andrewm@0: menu.addCommandItem(&commandManager_, StandardApplicationCommandIDs::paste); andrewm@0: menu.addCommandItem(&commandManager_, StandardApplicationCommandIDs::del); andrewm@0: menu.addSeparator(); andrewm@0: menu.addCommandItem(&commandManager_, StandardApplicationCommandIDs::selectAll); andrewm@0: } andrewm@0: else if(menuIndex == 2) { // Control andrewm@0: menu.addCommandItem(&commandManager_, kCommandRescanDevices); andrewm@0: menu.addSeparator(); andrewm@31: menu.addCommandItem(&commandManager_, kCommandLoggingStartStop); andrewm@31: menu.addCommandItem(&commandManager_, kCommandLoggingPlay); andrewm@31: menu.addSeparator(); andrewm@0: menu.addCommandItem(&commandManager_, kCommandEnableExperimentalMappings); andrewm@17: #ifdef ENABLE_TOUCHKEYS_SENSOR_TEST andrewm@17: menu.addCommandItem(&commandManager_, kCommandTestTouchkeySensors); andrewm@17: #endif andrewm@53: #ifdef ENABLE_TOUCHKEYS_FIRMWARE_UPDATE andrewm@53: menu.addCommandItem(&commandManager_, kCommandJumpToBootloader); andrewm@53: #endif andrewm@41: menu.addSeparator(); andrewm@41: menu.addCommandItem(&commandManager_, kCommandPreferences); andrewm@0: } andrewm@0: else if(menuIndex == 3) { // Window andrewm@0: menu.addCommandItem(&commandManager_, kCommandShowControlWindow); andrewm@0: menu.addCommandItem(&commandManager_, kCommandShowKeyboardWindow); andrewm@0: } andrewm@0: andrewm@0: return menu; andrewm@0: } andrewm@0: andrewm@0: void MainWindow::menuItemSelected(int menuItemID, int topLevelMenuIndex) { andrewm@0: // TODO andrewm@0: } andrewm@0: andrewm@0: // **** Command Manager methods ***** andrewm@0: andrewm@0: ApplicationCommandTarget* MainWindow::getNextCommandTarget() { andrewm@0: return findFirstTargetParentComponent(); andrewm@0: } andrewm@0: andrewm@0: // this returns the set of all commands that this target can perform.. andrewm@0: void MainWindow::getAllCommands(Array & commands) { andrewm@0: // this returns the set of all commands that this target can perform.. andrewm@0: const CommandID ids[] = { andrewm@0: // File andrewm@33: kCommandClearPreset, andrewm@33: kCommandOpenPreset, andrewm@33: kCommandSavePreset, andrewm@0: // Edit andrewm@0: StandardApplicationCommandIDs::undo, andrewm@0: StandardApplicationCommandIDs::redo, andrewm@0: StandardApplicationCommandIDs::cut, andrewm@0: StandardApplicationCommandIDs::copy, andrewm@0: StandardApplicationCommandIDs::paste, andrewm@0: StandardApplicationCommandIDs::del, andrewm@0: StandardApplicationCommandIDs::selectAll, andrewm@0: // Control andrewm@0: kCommandRescanDevices, andrewm@31: kCommandLoggingStartStop, andrewm@31: kCommandLoggingPlay, andrewm@0: kCommandEnableExperimentalMappings, andrewm@17: #ifdef ENABLE_TOUCHKEYS_SENSOR_TEST andrewm@17: kCommandTestTouchkeySensors, andrewm@17: #endif andrewm@53: #ifdef ENABLE_TOUCHKEYS_FIRMWARE_UPDATE andrewm@53: kCommandJumpToBootloader, andrewm@53: #endif andrewm@41: kCommandPreferences, andrewm@41: andrewm@0: // Window andrewm@0: kCommandShowControlWindow, andrewm@0: kCommandShowKeyboardWindow andrewm@0: }; andrewm@0: andrewm@0: commands.addArray (ids, numElementsInArray(ids)); andrewm@0: } andrewm@0: andrewm@0: // This method is used when something needs to find out the details about one of the commands andrewm@0: // that this object can perform.. andrewm@0: void MainWindow::getCommandInfo(CommandID commandID, ApplicationCommandInfo& result) { andrewm@0: const String presetsCategory("Presets"); andrewm@0: const String editsCategory("Editing"); andrewm@0: const String controlCategory("Control"); andrewm@0: const String windowCategory("Window"); andrewm@0: andrewm@0: switch (commandID) { andrewm@0: andrewm@0: // *** File Menu *** andrewm@33: case kCommandClearPreset: andrewm@33: result.setInfo("Clear Settings", "Clears the current settings", presetsCategory, 0); andrewm@0: result.setTicked(false); andrewm@37: result.setActive(true); andrewm@0: break; andrewm@0: case kCommandOpenPreset: andrewm@0: result.setInfo("Open Preset...", "Opens an existing preset", presetsCategory, 0); andrewm@0: result.setTicked(false); andrewm@33: result.setActive(true); andrewm@0: result.addDefaultKeypress ('O', ModifierKeys::commandModifier); andrewm@0: break; andrewm@0: case kCommandSavePreset: andrewm@33: result.setInfo("Save Preset...", "Saves the current preset", presetsCategory, 0); andrewm@0: result.setTicked(false); andrewm@33: result.setActive(true); andrewm@0: result.addDefaultKeypress ('S', ModifierKeys::commandModifier); andrewm@0: break; andrewm@0: // Quit command is handled by JuceApplication andrewm@0: andrewm@0: // *** Edit Menu *** andrewm@0: case StandardApplicationCommandIDs::undo: andrewm@0: result.setInfo("Undo", "Undo", editsCategory, 0); andrewm@0: result.setTicked(false); andrewm@0: result.setActive(false); andrewm@0: result.addDefaultKeypress ('Z', ModifierKeys::commandModifier); andrewm@0: break; andrewm@0: case StandardApplicationCommandIDs::redo: andrewm@0: result.setInfo("Redo", "Redo", editsCategory, 0); andrewm@0: result.setTicked(false); andrewm@0: result.setActive(false); andrewm@0: result.addDefaultKeypress ('Z', ModifierKeys::commandModifier | ModifierKeys::shiftModifier); andrewm@0: break; andrewm@0: case StandardApplicationCommandIDs::cut: andrewm@0: result.setInfo("Cut", "Cut", editsCategory, 0); andrewm@0: result.setTicked(false); andrewm@0: result.setActive(false); andrewm@0: result.addDefaultKeypress ('X', ModifierKeys::commandModifier); andrewm@0: break; andrewm@0: case StandardApplicationCommandIDs::copy: andrewm@0: result.setInfo("Copy", "Copy", editsCategory, 0); andrewm@0: result.setTicked(false); andrewm@0: result.setActive(false); andrewm@0: result.addDefaultKeypress ('C', ModifierKeys::commandModifier); andrewm@0: break; andrewm@0: case StandardApplicationCommandIDs::paste: andrewm@0: result.setInfo("Paste", "Paste", editsCategory, 0); andrewm@0: result.setTicked(false); andrewm@0: result.setActive(false); andrewm@0: result.addDefaultKeypress ('V', ModifierKeys::commandModifier); andrewm@0: break; andrewm@0: case StandardApplicationCommandIDs::del: andrewm@0: result.setInfo("Delete", "Delete", editsCategory, 0); andrewm@0: result.setTicked(false); andrewm@0: result.setActive(false); andrewm@0: break; andrewm@0: case StandardApplicationCommandIDs::selectAll: andrewm@0: result.setInfo("Select All", "Select All", editsCategory, 0); andrewm@0: result.setTicked(false); andrewm@0: result.setActive(false); andrewm@0: result.addDefaultKeypress ('A', ModifierKeys::commandModifier); andrewm@0: break; andrewm@0: andrewm@0: // *** Control Menu *** andrewm@0: case kCommandRescanDevices: andrewm@0: result.setInfo("Rescan Devices", "Rescans available TouchKeys and MIDI devices", controlCategory, 0); andrewm@0: result.setTicked(false); andrewm@28: result.setActive(true); andrewm@0: result.addDefaultKeypress ('R', ModifierKeys::commandModifier); andrewm@0: break; andrewm@31: case kCommandLoggingStartStop: andrewm@31: result.setInfo("Record Log File", "Records TouchKeys and MIDI data to file", controlCategory, 0); andrewm@31: result.setTicked(controller_.isLogging()); andrewm@53: result.setActive(!controller_.isPlayingLog()); andrewm@31: break; andrewm@31: case kCommandLoggingPlay: andrewm@31: result.setInfo("Play Log...", "Plays TouchKeys and MIDI from file", controlCategory, 0); andrewm@53: result.setTicked(controller_.isPlayingLog()); andrewm@53: result.setActive(!controller_.isLogging()); andrewm@31: break; andrewm@0: case kCommandEnableExperimentalMappings: andrewm@0: result.setInfo("Enable Experimental Mappings", "Enables mappings which are still experimental", controlCategory, 0); andrewm@0: result.setTicked(controller_.experimentalMappingsEnabled()); andrewm@0: break; andrewm@17: #ifdef ENABLE_TOUCHKEYS_SENSOR_TEST andrewm@17: case kCommandTestTouchkeySensors: andrewm@17: result.setInfo("Test TouchKeys Sensors", "Enables a test of individual TouchKeys sensors", controlCategory, 0); andrewm@17: result.setActive(controller_.availableTouchkeyDevices().size() > 0); andrewm@17: result.setTicked(controller_.touchkeySensorTestIsRunning()); andrewm@17: break; andrewm@17: #endif andrewm@53: #ifdef ENABLE_TOUCHKEYS_FIRMWARE_UPDATE andrewm@53: case kCommandJumpToBootloader: andrewm@53: result.setInfo("Go to Firmware Update Mode", "Puts the TouchKeys in firmware update mode", controlCategory, 0); andrewm@53: result.setActive(controller_.availableTouchkeyDevices().size() > 0); andrewm@53: result.setTicked(false); andrewm@53: break; andrewm@53: #endif andrewm@41: case kCommandPreferences: andrewm@41: result.setInfo("Preferences...", "General application preferences", controlCategory, 0); andrewm@41: result.setTicked(false); andrewm@41: result.setActive(true); andrewm@41: break; andrewm@0: andrewm@0: // *** Window Menu *** andrewm@0: case kCommandShowControlWindow: andrewm@0: result.setInfo("TouchKeys Controls", "Show control and mapping window", windowCategory, 0); andrewm@0: result.setTicked(false); andrewm@12: result.addDefaultKeypress ('1', ModifierKeys::commandModifier); andrewm@0: break; andrewm@0: case kCommandShowKeyboardWindow: andrewm@0: result.setInfo("Keyboard Display", "Show keyboard display", windowCategory, 0); andrewm@0: result.setTicked(false); andrewm@12: result.addDefaultKeypress ('2', ModifierKeys::commandModifier); andrewm@0: break; andrewm@0: andrewm@0: default: andrewm@0: break; andrewm@0: }; andrewm@0: } andrewm@0: andrewm@0: bool MainWindow::perform(const InvocationInfo& info) { andrewm@0: switch (info.commandID) andrewm@0: { andrewm@33: case kCommandClearPreset: andrewm@37: // Display an alert to confirm the user wants to delete this mapping andrewm@37: AlertWindow::showOkCancelBox (AlertWindow::QuestionIcon, andrewm@37: "Clear settings", andrewm@37: "Are you sure you want to clear all zones and mappings?", andrewm@37: String::empty, andrewm@37: String::empty, andrewm@37: 0, andrewm@37: ModalCallbackFunction::forComponent(alertBoxResultChosen, this)); andrewm@33: break; andrewm@33: case kCommandOpenPreset: andrewm@33: controller_.loadPresetWithDialog(); andrewm@33: break; andrewm@33: case kCommandSavePreset: andrewm@33: controller_.savePresetWithDialog(); andrewm@0: break; andrewm@0: case kCommandRescanDevices: andrewm@28: controller_.tellDevicesToUpdate(); andrewm@0: break; andrewm@31: case kCommandLoggingStartStop: andrewm@31: if(controller_.isLogging()) andrewm@31: controller_.stopLogging(); andrewm@31: else andrewm@31: controller_.startLogging(); andrewm@31: break; andrewm@31: case kCommandLoggingPlay: andrewm@53: if(controller_.isPlayingLog()) andrewm@53: controller_.stopPlayingLog(); andrewm@53: else andrewm@53: controller_.playLogWithDialog(); andrewm@31: break; andrewm@0: case kCommandEnableExperimentalMappings: andrewm@0: controller_.setExperimentalMappingsEnabled(!controller_.experimentalMappingsEnabled()); andrewm@0: break; andrewm@17: #ifdef ENABLE_TOUCHKEYS_SENSOR_TEST andrewm@17: case kCommandTestTouchkeySensors: andrewm@17: if(!controller_.touchkeySensorTestIsRunning()) andrewm@17: controller_.touchkeySensorTestStart(mainComponent_.currentTouchkeysSelectedPath().toUTF8(), controller_.touchkeyDeviceLowestMidiNote()); andrewm@17: else andrewm@17: controller_.touchkeySensorTestStop(); andrewm@17: break; andrewm@17: #endif andrewm@53: #ifdef ENABLE_TOUCHKEYS_FIRMWARE_UPDATE andrewm@53: case kCommandJumpToBootloader: andrewm@53: controller_.touchkeyJumpToBootloader(mainComponent_.currentTouchkeysSelectedPath().toUTF8()); andrewm@53: break; andrewm@53: #endif andrewm@41: case kCommandPreferences: andrewm@41: controller_.showPreferencesWindow(); andrewm@41: break; andrewm@0: case kCommandShowControlWindow: andrewm@0: toFront(true); andrewm@0: break; andrewm@0: case kCommandShowKeyboardWindow: andrewm@0: controller_.showKeyboardDisplayWindow(); andrewm@0: break; andrewm@0: andrewm@0: default: andrewm@0: return false; andrewm@0: }; andrewm@0: andrewm@0: return true; andrewm@0: } andrewm@37: andrewm@37: // Called when user clicks a result in the alert box to confirm deletion andrewm@37: void MainWindow::alertBoxResultChosen(int result, MainWindow *item) { andrewm@37: if(result != 0) { andrewm@37: item->clearPreset(); andrewm@37: } andrewm@37: } andrewm@50: andrewm@50: #endif // TOUCHKEYS_NO_GUI