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