mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-11 23:54:18 +00:00
286 lines
10 KiB
C++
286 lines
10 KiB
C++
/*
|
|
==============================================================================
|
|
|
|
This file is part of the JUCE library.
|
|
Copyright (c) 2017 - ROLI Ltd.
|
|
|
|
JUCE is an open source library subject to commercial or open-source
|
|
licensing.
|
|
|
|
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
|
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
|
27th April 2017).
|
|
|
|
End User License Agreement: www.juce.com/juce-5-licence
|
|
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
|
|
|
Or: You may also use this code under the terms of the GPL v3 (see
|
|
www.gnu.org/licenses).
|
|
|
|
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
|
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
|
DISCLAIMED.
|
|
|
|
==============================================================================
|
|
*/
|
|
|
|
#include "../jucer_Headers.h"
|
|
#include "jucer_DependencyPathPropertyComponent.h"
|
|
|
|
//==============================================================================
|
|
DependencyPathValueSource::DependencyPathValueSource (const Value& projectSettingsPath,
|
|
Identifier globalSettingsKey,
|
|
DependencyPathOS osThisSettingAppliesTo)
|
|
: projectSettingsValue (projectSettingsPath),
|
|
globalKey (globalSettingsKey),
|
|
os (osThisSettingAppliesTo),
|
|
globalSettingsValue (getAppSettings().getStoredPath (globalKey)),
|
|
fallbackValue (getAppSettings().getFallbackPathForOS (globalKey, os))
|
|
{
|
|
globalSettingsValue.addListener (this);
|
|
fallbackValue.addListener (this);
|
|
}
|
|
|
|
bool DependencyPathValueSource::isValidPath (const File& relativeTo) const
|
|
{
|
|
// if we are on another OS than the one which this path setting is for,
|
|
// we have no way of knowing whether the path is valid - so just assume it is:
|
|
if (! appliesToThisOS())
|
|
return true;
|
|
|
|
return getAppSettings().isGlobalPathValid (relativeTo, globalKey, getValue().toString());
|
|
}
|
|
|
|
bool DependencyPathValueSource::isValidPath() const
|
|
{
|
|
return isValidPath (File::getCurrentWorkingDirectory());
|
|
}
|
|
|
|
//==============================================================================
|
|
DependencyPathPropertyComponent::DependencyPathPropertyComponent (const File& pathRelativeToUse,
|
|
const Value& value,
|
|
const String& propertyName)
|
|
try : TextPropertyComponent (propertyName, 1024, false),
|
|
pathRelativeTo (pathRelativeToUse),
|
|
pathValue (value),
|
|
pathValueSource (dynamic_cast<DependencyPathValueSource&> (pathValue.getValueSource()))
|
|
{
|
|
bool initialValueIsEmpty = ! pathValueSource.isUsingProjectSettings();
|
|
|
|
getValue().referTo (pathValue);
|
|
|
|
// the following step is necessary because the above referTo() has internally called setValue(),
|
|
// which has set the project value to whatever is displayed in the label (this may be the
|
|
// global/fallback value). In this case we have to reset the project value to blank:
|
|
if (initialValueIsEmpty)
|
|
getValue().setValue (String());
|
|
|
|
getValue().addListener (this);
|
|
|
|
if (Label* label = dynamic_cast<Label*> (getChildComponent (0)))
|
|
label->addListener (this);
|
|
else
|
|
jassertfalse;
|
|
|
|
lookAndFeelChanged();
|
|
}
|
|
catch (const std::bad_cast&)
|
|
{
|
|
// a DependencyPathPropertyComponent must be initialised with a Value
|
|
// that is referring to a DependencyPathValueSource!
|
|
jassertfalse;
|
|
throw;
|
|
}
|
|
|
|
void DependencyPathPropertyComponent::valueChanged (Value& value)
|
|
{
|
|
// this callback handles the update of this setting in case
|
|
// the user changed the global preferences.
|
|
if (value.refersToSameSourceAs (pathValue) && pathValueSource.isUsingGlobalSettings())
|
|
textWasEdited();
|
|
}
|
|
|
|
void DependencyPathPropertyComponent::textWasEdited()
|
|
{
|
|
setColour (textColourId, getTextColourToDisplay());
|
|
TextPropertyComponent::textWasEdited();
|
|
}
|
|
|
|
Colour DependencyPathPropertyComponent::getTextColourToDisplay() const
|
|
{
|
|
if (! pathValueSource.isUsingProjectSettings())
|
|
return pathValueSource.isValidPath (pathRelativeTo) ? findColour (widgetTextColourId).withMultipliedAlpha (0.5f)
|
|
: Colours::red.withMultipliedAlpha (0.5f);
|
|
|
|
return pathValueSource.isValidPath (pathRelativeTo) ? findColour (widgetTextColourId)
|
|
: Colours::red;
|
|
}
|
|
|
|
void DependencyPathPropertyComponent::labelTextChanged (Label*)
|
|
{
|
|
}
|
|
|
|
void DependencyPathPropertyComponent::editorShown (Label* /*label*/, TextEditor& editor)
|
|
{
|
|
if (! pathValueSource.isUsingProjectSettings())
|
|
editor.setText (String(), dontSendNotification);
|
|
}
|
|
|
|
void DependencyPathPropertyComponent::editorHidden (Label*, TextEditor&)
|
|
{
|
|
}
|
|
|
|
void DependencyPathPropertyComponent::lookAndFeelChanged()
|
|
{
|
|
textWasEdited();
|
|
}
|
|
|
|
//==============================================================================
|
|
DependencyFilePathPropertyComponent::DependencyFilePathPropertyComponent (Value& value,
|
|
const String& propertyDescription,
|
|
bool isDir,
|
|
const String& wc,
|
|
const File& rootToUseForRelativePaths)
|
|
try : TextPropertyComponent (propertyDescription, 1024, false),
|
|
pathRelativeTo (rootToUseForRelativePaths),
|
|
pathValue (value),
|
|
pathValueSource (dynamic_cast<DependencyPathValueSource&> (pathValue.getValueSource())),
|
|
browseButton ("..."),
|
|
isDirectory (isDir),
|
|
wildcards (wc)
|
|
{
|
|
auto initialValueIsEmpty = ! pathValueSource.isUsingProjectSettings();
|
|
|
|
getValue().referTo (pathValue);
|
|
|
|
if (initialValueIsEmpty)
|
|
getValue().setValue (String());
|
|
|
|
getValue().addListener (this);
|
|
|
|
if (auto* label = dynamic_cast<Label*> (getChildComponent (0)))
|
|
label->addListener (this);
|
|
else
|
|
jassertfalse;
|
|
|
|
setInterestedInFileDrag (false);
|
|
|
|
addAndMakeVisible (browseButton);
|
|
browseButton.addListener (this);
|
|
|
|
lookAndFeelChanged();
|
|
}
|
|
catch (const std::bad_cast&)
|
|
{
|
|
// a DependencyPathPropertyComponent must be initialised with a Value
|
|
// that is referring to a DependencyPathValueSource!
|
|
jassertfalse;
|
|
throw;
|
|
}
|
|
|
|
void DependencyFilePathPropertyComponent::resized()
|
|
{
|
|
auto bounds = getLookAndFeel().getPropertyComponentContentPosition (*this);
|
|
|
|
browseButton.setBounds (bounds.removeFromRight (30));
|
|
getChildComponent (0)->setBounds (bounds);
|
|
}
|
|
|
|
void DependencyFilePathPropertyComponent::paintOverChildren (Graphics& g)
|
|
{
|
|
if (highlightForDragAndDrop)
|
|
{
|
|
g.setColour (findColour (defaultHighlightColourId).withAlpha (0.5f));
|
|
g.fillRect (getChildComponent (0)->getBounds());
|
|
}
|
|
}
|
|
|
|
void DependencyFilePathPropertyComponent::filesDropped (const StringArray& files, int, int)
|
|
{
|
|
const File firstFile (files[0]);
|
|
|
|
if (isDirectory)
|
|
setTo (firstFile.isDirectory() ? firstFile
|
|
: firstFile.getParentDirectory());
|
|
else
|
|
setTo (firstFile);
|
|
|
|
highlightForDragAndDrop = false;
|
|
}
|
|
|
|
void DependencyFilePathPropertyComponent::setTo (const File& f)
|
|
{
|
|
pathValue = (pathRelativeTo == File()) ? f.getFullPathName()
|
|
: f.getRelativePathFrom (pathRelativeTo);
|
|
|
|
textWasEdited();
|
|
}
|
|
|
|
void DependencyFilePathPropertyComponent::enablementChanged()
|
|
{
|
|
getValue().referTo (isEnabled() ? pathValue
|
|
: pathValueSource.appliesToThisOS() ? pathValueSource.getGlobalSettingsValue()
|
|
: pathValueSource.getFallbackSettingsValue());
|
|
textWasEdited();
|
|
repaint();
|
|
}
|
|
|
|
void DependencyFilePathPropertyComponent::textWasEdited()
|
|
{
|
|
setColour (textColourId, getTextColourToDisplay());
|
|
TextPropertyComponent::textWasEdited();
|
|
}
|
|
|
|
void DependencyFilePathPropertyComponent::valueChanged (Value& value)
|
|
{
|
|
if ((value.refersToSameSourceAs (pathValue) && pathValueSource.isUsingGlobalSettings())
|
|
|| value.refersToSameSourceAs (pathValueSource.getGlobalSettingsValue()))
|
|
textWasEdited();
|
|
}
|
|
|
|
void DependencyFilePathPropertyComponent::editorShown (Label*, TextEditor& editor)
|
|
{
|
|
if (! pathValueSource.isUsingProjectSettings())
|
|
editor.setText (String(), dontSendNotification);
|
|
}
|
|
|
|
void DependencyFilePathPropertyComponent::buttonClicked (Button*)
|
|
{
|
|
auto currentFile = pathRelativeTo.getChildFile (pathValue.toString());
|
|
|
|
if (isDirectory)
|
|
{
|
|
FileChooser chooser ("Select directory", currentFile);
|
|
|
|
if (chooser.browseForDirectory())
|
|
setTo (chooser.getResult());
|
|
}
|
|
else
|
|
{
|
|
FileChooser chooser ("Select file", currentFile, wildcards);
|
|
|
|
if (chooser.browseForFileToOpen())
|
|
setTo (chooser.getResult());
|
|
}
|
|
}
|
|
|
|
Colour DependencyFilePathPropertyComponent::getTextColourToDisplay() const
|
|
{
|
|
auto alpha = 1.0f;
|
|
auto key = pathValueSource.getKey();
|
|
const auto& globalSettingsValue = pathValueSource.getGlobalSettingsValue();
|
|
|
|
if (! pathValueSource.isUsingProjectSettings() && isEnabled())
|
|
alpha = 0.5f;
|
|
|
|
if ((key == Ids::defaultUserModulePath && getValue().toString().contains (";")) || ! pathValueSource.appliesToThisOS())
|
|
return findColour (widgetTextColourId).withMultipliedAlpha (alpha);
|
|
|
|
auto usingGlobalPath = (getValue().refersToSameSourceAs (globalSettingsValue));
|
|
|
|
auto isValidPath = getAppSettings().isGlobalPathValid (pathRelativeTo, key,
|
|
(usingGlobalPath ? globalSettingsValue : pathValue).toString());
|
|
|
|
return isValidPath ? findColour (widgetTextColourId).withMultipliedAlpha (alpha)
|
|
: Colours::red.withMultipliedAlpha (alpha);
|
|
}
|