PresetMenuComponent.cpp (5235B)
1 /*---------------------------------------------------------------------------------------- 2 3 Copyright (c) 2023 AUDIOKINETIC Inc. 4 5 This file is licensed to use under the license available at: 6 https://github.com/audiokinetic/ReaWwise/blob/main/License.txt (the "License"). 7 You may not use this file except in compliance with the License. 8 9 Unless required by applicable law or agreed to in writing, software distributed 10 under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 11 CONDITIONS OF ANY KIND, either express or implied. See the License for the 12 specific language governing permissions and limitations under the License. 13 14 ----------------------------------------------------------------------------------------*/ 15 16 #include "PresetMenuComponent.h" 17 18 #include "BinaryData.h" 19 #include "Helpers/PersistanceHelper.h" 20 #include "Model/IDs.h" 21 22 namespace AK::WwiseTransfer 23 { 24 namespace PresetMenuComponentConstants 25 { 26 constexpr auto loadFlags = juce::FileBrowserComponent::openMode | 27 juce::FileBrowserComponent::canSelectFiles; 28 constexpr auto saveFlags = juce::FileBrowserComponent::saveMode | 29 juce::FileBrowserComponent::canSelectFiles | juce::FileBrowserComponent::warnAboutOverwriting; 30 constexpr auto fileFilter = "*.xml"; 31 } // namespace PresetMenuComponentConstants 32 33 PresetMenuComponent::PresetMenuComponent(juce::ValueTree appState, ApplicationProperties& applicationProperties, const juce::String& applicationName) 34 : CustomDrawableButton("PresetMenuButton", juce::Drawable::createFromImageData(BinaryData::General_FolderWithTriangle_Normal_svg, BinaryData::General_FolderWithTriangle_Normal_svgSize)) 35 , hierarchyMapping(appState.getChildWithName(IDs::hierarchyMapping)) 36 , presetFolder(juce::File::getSpecialLocation(juce::File::SpecialLocationType::userApplicationDataDirectory).getChildFile(applicationName).getChildFile("Presets")) 37 , applicationProperties(applicationProperties) 38 { 39 if(!presetFolder.exists()) 40 presetFolder.createDirectory(); 41 42 setTooltip("Manage Presets"); 43 44 onClick = [this] 45 { 46 showMenu(); 47 }; 48 } 49 50 void PresetMenuComponent::showMenu() 51 { 52 using namespace PresetMenuComponentConstants; 53 54 juce::PopupMenu presetMenu; 55 presetMenu.setLookAndFeel(&getLookAndFeel()); 56 57 auto onSavePreset = [this] 58 { 59 fileChooser = std::make_unique<juce::FileChooser>("Save preset...", presetFolder, fileFilter); 60 61 auto onFileChosen = [this](const juce::FileChooser& chooser) 62 { 63 auto file = chooser.getResult(); 64 65 auto createResult = file.create(); 66 67 if(createResult) 68 { 69 const auto presetData = PersistanceHelper::hierarchyMappingToPresetData(hierarchyMapping); 70 file.replaceWithText(presetData); 71 applicationProperties.addRecentHierarchyMappingPreset(file.getFullPathName()); 72 } 73 // An empty path indicates that the file is invalid. This is the behavior for when the user clicks cancel in the file chooser 74 // https://docs.juce.com/master/classFile.html#a38506545c1402119b5fef7bcf6289fa9 75 else if(!file.getFullPathName().isEmpty()) 76 { 77 juce::AlertWindow::showMessageBoxAsync(juce::MessageBoxIconType::InfoIcon, "Save Preset", createResult.getErrorMessage()); 78 } 79 }; 80 81 fileChooser->launchAsync(saveFlags, onFileChosen); 82 }; 83 84 presetMenu.addItem("Save Preset...", onSavePreset); 85 86 auto onLoadPreset = [this] 87 { 88 fileChooser = std::make_unique<juce::FileChooser>("Select preset...", presetFolder, fileFilter); 89 90 auto onFileChosen = [this](const juce::FileChooser& chooser) 91 { 92 auto presetFile = chooser.getResult(); 93 if(presetFile.exists()) 94 loadPreset(presetFile); 95 }; 96 97 fileChooser->launchAsync(loadFlags, onFileChosen); 98 }; 99 100 presetMenu.addItem("Load Preset...", onLoadPreset); 101 102 auto recentPresets = applicationProperties.getRecentHierarchyMappingPresets(); 103 104 juce::PopupMenu recentMenu; 105 106 for(const auto& recentPreset : recentPresets) 107 { 108 auto onRecentPresetSelected = [this, recentPreset = recentPreset] 109 { 110 loadPreset(recentPreset); 111 }; 112 113 recentMenu.addItem(recentPreset, onRecentPresetSelected); 114 } 115 116 recentMenu.addSeparator(); 117 118 auto onClearRecentPresets = [this] 119 { 120 applicationProperties.clearRecentHierarchyMappingPresets(); 121 }; 122 123 recentMenu.addItem("Clear Recent Presets", onClearRecentPresets); 124 125 presetMenu.addSubMenu("Recent Preset", recentMenu, !recentPresets.isEmpty()); 126 127 const auto opts = juce::PopupMenu::Options().withTargetComponent(this); 128 presetMenu.showMenuAsync(opts); 129 } 130 131 void PresetMenuComponent::loadPreset(const juce::File& presetFile) 132 { 133 auto presetData = presetFile.loadFileAsString(); 134 auto hierarchyMappingTemp = PersistanceHelper::presetDataToHierarchyMapping(presetData); 135 136 if(hierarchyMappingTemp.isValid()) 137 { 138 hierarchyMapping.copyPropertiesAndChildrenFrom(hierarchyMappingTemp, nullptr); 139 applicationProperties.addRecentHierarchyMappingPreset(presetFile.getFullPathName()); 140 } 141 else 142 { 143 juce::AlertWindow::showMessageBoxAsync(juce::MessageBoxIconType::InfoIcon, "Load Preset", "Unable to load preset! The preset file is corrupt."); 144 applicationProperties.removeRecentHierarchyMappingPreset(presetFile.getFullPathName()); 145 } 146 } 147 148 } // namespace AK::WwiseTransfer