/* ============================================================================== This file is part of the JUCE library. Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) b) the Affero GPL v3 Details of these licenses can be found at: www.gnu.org/licenses JUCE 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. ------------------------------------------------------------------------------ To release a closed-source product which uses JUCE, commercial licenses are available: visit www.juce.com for more information. ============================================================================== */ #pragma once //============================================================================== /** This ValueSource type implements the fallback logic required for dependency path settings: use the project exporter value; if this is empty, fall back to the global preference value; if the exporter is supposed to run on another OS and we don't know what the global preferences on that other machine are, fall back to a generic OS-specific fallback value. */ class DependencyPathValueSource : public Value::ValueSource, private Value::Listener { public: DependencyPathValueSource (const Value& projectSettingsPath, Identifier globalSettingsKey, DependencyPathOS osThisSettingAppliesTo); /** This gets the currently used value, which may be either the project setting, the global setting, or the fallback value. */ var getValue() const override { if (isUsingProjectSettings()) return projectSettingsValue.getValue(); if (isUsingGlobalSettings()) return globalSettingsValue.getValue(); return fallbackValue; } void setValue (const var& newValue) override { projectSettingsValue = newValue; if (isUsingProjectSettings()) sendChangeMessage (false); } bool isUsingProjectSettings() const { return projectSettingsValueIsValid(); } bool isUsingGlobalSettings() const { return ! projectSettingsValueIsValid() && globalSettingsValueIsValid(); } bool isUsingFallbackValue() const { return ! projectSettingsValueIsValid() && !globalSettingsValueIsValid(); } bool appliesToThisOS() const { return os == TargetOS::getThisOS(); } bool isValidPath (const File& relativeTo) const; bool isValidPath() const; private: void valueChanged (Value& value) override { if ((value.refersToSameSourceAs (globalSettingsValue) && isUsingGlobalSettings())) { sendChangeMessage (true); setValue (String()); // make sure that the project-specific value is still blank } } /** This defines when to use the project setting, and when to consider it invalid and to fall back to the global setting or the fallback value. */ bool projectSettingsValueIsValid() const { return ! projectSettingsValue.toString().isEmpty(); } /** This defines when to use the global setting - given the project setting is invalid, and when to fall back to the fallback value instead. */ bool globalSettingsValueIsValid() const { // only use the global settings if they are set on the same OS // that this setting is for! DependencyPathOS thisOS = TargetOS::getThisOS(); return thisOS == TargetOS::unknown ? false : os == thisOS; } /** the dependency path setting as set in this Projucer project. */ Value projectSettingsValue; /** the global key used in the application settings for the global setting value. needed for checking whether the path is valid. */ Identifier globalKey; /** on what operating system should this dependency path be used? note that this is *not* the os that is targeted by the project, but rather the os on which the project will be compiled (= on which the path settings need to be set correctly). */ DependencyPathOS os; /** the dependency path global setting on this machine. used when there value set for this project is invalid. */ Value globalSettingsValue; /** the dependency path fallback setting. used instead of the global setting whenever the latter doesn't apply, e.g. the setting is for another OS than the ome this machine is running. */ String fallbackValue; }; //============================================================================== class DependencyPathPropertyComponent : public TextPropertyComponent, private Value::Listener, private Label::Listener { public: DependencyPathPropertyComponent (const File& pathRelativeToUse, const Value& value, const String& propertyName); private: /** This function defines what colour the label text should assume depending on the current state of the value the component tracks. */ Colour getTextColourToDisplay() const; /** This function handles path changes because of user input. */ void textWasEdited() override; /** This function handles path changes because the global path changed. */ void valueChanged (Value& value) override; /** If the dependency path is relative, relative to which directory should we check if an object is available. */ File pathRelativeTo; /** the value that represents this dependency path setting. */ Value pathValue; /** a reference to the value source that this value refers to. */ DependencyPathValueSource& pathValueSource; // Label::Listener overrides: void labelTextChanged (Label* labelThatHasChanged) override; void editorShown (Label*, TextEditor&) override; void editorHidden (Label*, TextEditor&) override; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DependencyPathPropertyComponent) };