Mercurial > hg > touchkeys
view Source/GUI/MappingListComponent.cpp @ 55:19650b4076ee
Bug fixes for multiple MIDI zones and having polyphonic mode come up correctly on preset load.
author | Andrew McPherson <andrewm@eecs.qmul.ac.uk> |
---|---|
date | Fri, 23 Nov 2018 15:39:25 +0000 |
parents | 85577160a0d4 |
children |
line wrap: on
line source
/* TouchKeys: multi-touch musical keyboard control software Copyright (c) 2013 Andrew McPherson This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. ===================================================================== MappingListComponent.cpp: manages a ListBox to display the current mappigns associated with a keyboard segment. */ #ifndef TOUCHKEYS_NO_GUI #include "../JuceLibraryCode/JuceHeader.h" #include "MappingListComponent.h" #include "MappingExtendedEditorWindow.h" //============================================================================== MappingListComponent::MappingListComponent() : controller_(0), keyboardSegment_(0), lastMappingFactoryIdentifier_(-1) { // In your constructor, you should add any child components, and // initialise any special settings that your component needs. addAndMakeVisible(&listBox_); listBox_.setModel(this); listBox_.setColour(ListBox::outlineColourId, Colours::grey); listBox_.setOutlineThickness(1); listBox_.setRowHeight(72); } MappingListComponent::~MappingListComponent() { clearExtendedEditorWindows(); } void MappingListComponent::resized() { // This method is where you should set the bounds of any child // components that your component contains.. listBox_.setBoundsInset (BorderSize<int> (4)); } // Delete the given factory from the mapping list void MappingListComponent::deleteMapping(MappingFactory* factory) { if(keyboardSegment_ == 0 || factory == 0) return; keyboardSegment_->removeMappingFactory(factory); } int MappingListComponent::getNumRows() { if(controller_ == 0 || keyboardSegment_ == 0) return 0; return keyboardSegment_->mappingFactories().size(); } // Given a row number and a possibly an existing component, return the component // that should be drawn in this row of the list. Whenever a new component is created, // the existing one should be deleted by this method (according to Juce docs). Component* MappingListComponent::refreshComponentForRow(int rowNumber, bool isRowSelected, Component *existingComponentToUpdate) { if(keyboardSegment_ == 0) return 0; //std::cout << "refreshing component for row " << rowNumber << " (given " << existingComponentToUpdate << ")\n"; if(rowNumber < 0 || rowNumber >= getNumRows()) { if(existingComponentToUpdate != 0) delete existingComponentToUpdate; return 0; } // Get the current component for the row, creating it if it doesn't exist MappingListItem *listItem = static_cast<MappingListItem*>(existingComponentToUpdate); if(listItem == 0) { listItem = new MappingListItem(*this); listItem->setMappingFactory(keyboardSegment_->mappingFactories()[rowNumber]); //std::cout << "item " << listItem << " was updated to factory " << keyboardSegment_->mappingFactories()[rowNumber] << std::endl; } else { // Component exists; does it still point to a factory? if(rowNumber >= keyboardSegment_->mappingFactories().size()) { //std::cout << "Deleting component " << listItem << std::endl; delete listItem; return 0; } else if(keyboardSegment_->mappingFactories()[rowNumber] != listItem->mappingFactory()) { //std::cout << "Changing item " << listItem << " to point to factory " << keyboardSegment_->mappingFactories()[rowNumber] << std::endl; listItem->setMappingFactory(keyboardSegment_->mappingFactories()[rowNumber]); } } return listItem; } // Return whether a given component is selected or not (called by MappingListItem) bool MappingListComponent::isComponentSelected(Component *component) { int rowNumber = listBox_.getRowNumberOfComponent(component); if(rowNumber < 0) return false; return listBox_.isRowSelected(rowNumber); } void MappingListComponent::synchronize() { if(keyboardSegment_ != 0) { if(lastMappingFactoryIdentifier_ != keyboardSegment_->mappingFactoryUniqueIdentifier()) { lastMappingFactoryIdentifier_ = keyboardSegment_->mappingFactoryUniqueIdentifier(); listBox_.updateContent(); updateExtendedEditorWindows(); } } for(int i = 0; i < getNumRows(); i++) { MappingListItem *listItem = static_cast<MappingListItem*>(listBox_.getComponentForRowNumber(i)); if(listItem != 0) listItem->synchronize(); } synchronizeExtendedEditorWindows(); } // Open an extended editor window for the given component // Store the new window in the list; it is deleted when it is closed void MappingListComponent::openExtendedEditorWindow(MappingFactory *factory) { if(factory == 0) return; ScopedLock sl(extendedEditorWindowsMutex_); MappingExtendedEditorWindow *window = new MappingExtendedEditorWindow(*this, *keyboardSegment_, *factory); extendedEditorWindows_.push_back(window); } // Close an extended editor window and remove it from the list void MappingListComponent::closeExtendedEditorWindow(MappingExtendedEditorWindow *window) { ScopedLock sl(extendedEditorWindowsMutex_); closeExtendedEditorWindowHelper(window); } MappingExtendedEditorWindow* MappingListComponent::extendedEditorWindowForFactory(MappingFactory *factory) { ScopedLock sl(extendedEditorWindowsMutex_); list<MappingExtendedEditorWindow*>::iterator it; for(it = extendedEditorWindows_.begin(); it != extendedEditorWindows_.end(); ++it) { if((*it)->factory() == factory) return *it; } return 0; } // Update extended editor windows void MappingListComponent::synchronizeExtendedEditorWindows() { // Update extended editor windows ScopedLock sl(extendedEditorWindowsMutex_); list<MappingExtendedEditorWindow*>::iterator it; for(it = extendedEditorWindows_.begin(); it != extendedEditorWindows_.end(); ++it) { (*it)->synchronize(); } } // Close an extended editor window and remove it from the list (interval version without lock) void MappingListComponent::closeExtendedEditorWindowHelper(MappingExtendedEditorWindow *window) { window->setVisible(false); list<MappingExtendedEditorWindow*>::iterator it; bool found = true; // Remove this window from the list (handling multiple entries just in case) while(found) { found = false; for(it = extendedEditorWindows_.begin(); it != extendedEditorWindows_.end(); ++it) { if(*it == window) { extendedEditorWindows_.erase(it); found = true; break; } } } // Delete the window which in turn deletes the editor component delete window; } // Find the invalid extended editor windows and close them void MappingListComponent::updateExtendedEditorWindows() { ScopedLock sl(extendedEditorWindowsMutex_); list<MappingExtendedEditorWindow*>::iterator it; bool found = true; // Remove the window from the list if it is invalid while(found) { found = false; for(it = extendedEditorWindows_.begin(); it != extendedEditorWindows_.end(); ++it) { if(!(*it)->isValid()) { closeExtendedEditorWindowHelper(*it); found = true; break; } } } } // Remove all extend editor windows void MappingListComponent::clearExtendedEditorWindows() { ScopedLock sl(extendedEditorWindowsMutex_); list<MappingExtendedEditorWindow*>::iterator it; for(it = extendedEditorWindows_.begin(); it != extendedEditorWindows_.end(); ++it) { delete *it; } extendedEditorWindows_.clear(); } #endif // TOUCHKEYS_NO_GUI