ReaWwise

REAPER extension
Log | Files | Refs | Submodules

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