1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

Projucer: Removed DependencyPathPropertyComponent and replaced it with an updated FilePathPropertyComponent that supports ValueWithDefault

This commit is contained in:
ed 2018-10-22 16:38:04 +01:00
parent dbe40552a7
commit 3f2f2f65a4
12 changed files with 150 additions and 738 deletions

View file

@ -114,7 +114,6 @@ OBJECTS_APP := \
$(JUCE_OBJDIR)/jucer_FileHelpers_54f12f83.o \
$(JUCE_OBJDIR)/jucer_MiscUtilities_31fc8dd8.o \
$(JUCE_OBJDIR)/jucer_PIPGenerator_fd3402c7.o \
$(JUCE_OBJDIR)/jucer_DependencyPathPropertyComponent_5d68c773.o \
$(JUCE_OBJDIR)/jucer_Icons_d02d18f1.o \
$(JUCE_OBJDIR)/jucer_JucerTreeViewBase_9b9f2ff0.o \
$(JUCE_OBJDIR)/jucer_ProjucerLookAndFeel_3b20291d.o \
@ -372,11 +371,6 @@ $(JUCE_OBJDIR)/jucer_PIPGenerator_fd3402c7.o: ../../Source/Utility/PIPs/jucer_PI
@echo "Compiling jucer_PIPGenerator.cpp"
$(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<"
$(JUCE_OBJDIR)/jucer_DependencyPathPropertyComponent_5d68c773.o: ../../Source/Utility/UI/PropertyComponents/jucer_DependencyPathPropertyComponent.cpp
-$(V_AT)mkdir -p $(JUCE_OBJDIR)
@echo "Compiling jucer_DependencyPathPropertyComponent.cpp"
$(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<"
$(JUCE_OBJDIR)/jucer_Icons_d02d18f1.o: ../../Source/Utility/UI/jucer_Icons.cpp
-$(V_AT)mkdir -p $(JUCE_OBJDIR)
@echo "Compiling jucer_Icons.cpp"

View file

@ -261,10 +261,6 @@
isa = PBXBuildFile;
fileRef = 191330B20DAC08B890656EA0;
};
2BEC1197D981951D8A897F01 = {
isa = PBXBuildFile;
fileRef = D859E9EA11A71BD6E85DC649;
};
D0E26EB54B0087C8BE3D541E = {
isa = PBXBuildFile;
fileRef = 846B2A670C5A19DE0039E11A;
@ -2271,13 +2267,6 @@
path = "../../JuceLibraryCode/include_juce_cryptography.mm";
sourceTree = "SOURCE_ROOT";
};
D859E9EA11A71BD6E85DC649 = {
isa = PBXFileReference;
lastKnownFileType = sourcecode.cpp.cpp;
name = "jucer_DependencyPathPropertyComponent.cpp";
path = "../../Source/Utility/UI/PropertyComponents/jucer_DependencyPathPropertyComponent.cpp";
sourceTree = "SOURCE_ROOT";
};
D91E7F8FEF9290195D56782C = {
isa = PBXFileReference;
lastKnownFileType = sourcecode.c.h;
@ -2551,13 +2540,6 @@
path = "../../Source/BinaryData/Icons/wizard_Highlight.svg";
sourceTree = "SOURCE_ROOT";
};
F8F94093A0963D86BD27A95D = {
isa = PBXFileReference;
lastKnownFileType = sourcecode.c.h;
name = "jucer_DependencyPathPropertyComponent.h";
path = "../../Source/Utility/UI/PropertyComponents/jucer_DependencyPathPropertyComponent.h";
sourceTree = "SOURCE_ROOT";
};
F9111E150CFF155329D44853 = {
isa = PBXFileReference;
lastKnownFileType = sourcecode.cpp.cpp;
@ -3039,8 +3021,6 @@
isa = PBXGroup;
children = (
9EB33734D0DBD0370AB1247B,
D859E9EA11A71BD6E85DC649,
F8F94093A0963D86BD27A95D,
E367FC2BDAF5EBA48D767FBB,
59F8A47C0020D62C8836A1E7,
);
@ -3463,7 +3443,6 @@
BF913199032B4CE970E82AA3,
25EF9B3FECB4C9F0F522DCAA,
638C7247B6DBA67EFE46E124,
2BEC1197D981951D8A897F01,
D0E26EB54B0087C8BE3D541E,
468548FB21D264DC12321327,
6ECB2F11D2F593FACCCF99DB,

View file

@ -240,7 +240,6 @@
<ClCompile Include="..\..\Source\Utility\Helpers\jucer_FileHelpers.cpp"/>
<ClCompile Include="..\..\Source\Utility\Helpers\jucer_MiscUtilities.cpp"/>
<ClCompile Include="..\..\Source\Utility\PIPs\jucer_PIPGenerator.cpp"/>
<ClCompile Include="..\..\Source\Utility\UI\PropertyComponents\jucer_DependencyPathPropertyComponent.cpp"/>
<ClCompile Include="..\..\Source\Utility\UI\jucer_Icons.cpp"/>
<ClCompile Include="..\..\Source\Utility\UI\jucer_JucerTreeViewBase.cpp"/>
<ClCompile Include="..\..\Source\Utility\UI\jucer_ProjucerLookAndFeel.cpp"/>
@ -1627,7 +1626,6 @@
<ClInclude Include="..\..\Source\Utility\Helpers\jucer_ValueSourceHelpers.h"/>
<ClInclude Include="..\..\Source\Utility\PIPs\jucer_PIPGenerator.h"/>
<ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_ColourPropertyComponent.h"/>
<ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_DependencyPathPropertyComponent.h"/>
<ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_FilePathPropertyComponent.h"/>
<ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_PropertyComponentsWithEnablement.h"/>
<ClInclude Include="..\..\Source\Utility\UI\jucer_IconButton.h"/>

View file

@ -496,9 +496,6 @@
<ClCompile Include="..\..\Source\Utility\PIPs\jucer_PIPGenerator.cpp">
<Filter>Projucer\Utility\PIPs</Filter>
</ClCompile>
<ClCompile Include="..\..\Source\Utility\UI\PropertyComponents\jucer_DependencyPathPropertyComponent.cpp">
<Filter>Projucer\Utility\UI\PropertyComponents</Filter>
</ClCompile>
<ClCompile Include="..\..\Source\Utility\UI\jucer_Icons.cpp">
<Filter>Projucer\Utility\UI</Filter>
</ClCompile>
@ -2325,9 +2322,6 @@
<ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_ColourPropertyComponent.h">
<Filter>Projucer\Utility\UI\PropertyComponents</Filter>
</ClInclude>
<ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_DependencyPathPropertyComponent.h">
<Filter>Projucer\Utility\UI\PropertyComponents</Filter>
</ClInclude>
<ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_FilePathPropertyComponent.h">
<Filter>Projucer\Utility\UI\PropertyComponents</Filter>
</ClInclude>

View file

@ -240,7 +240,6 @@
<ClCompile Include="..\..\Source\Utility\Helpers\jucer_FileHelpers.cpp"/>
<ClCompile Include="..\..\Source\Utility\Helpers\jucer_MiscUtilities.cpp"/>
<ClCompile Include="..\..\Source\Utility\PIPs\jucer_PIPGenerator.cpp"/>
<ClCompile Include="..\..\Source\Utility\UI\PropertyComponents\jucer_DependencyPathPropertyComponent.cpp"/>
<ClCompile Include="..\..\Source\Utility\UI\jucer_Icons.cpp"/>
<ClCompile Include="..\..\Source\Utility\UI\jucer_JucerTreeViewBase.cpp"/>
<ClCompile Include="..\..\Source\Utility\UI\jucer_ProjucerLookAndFeel.cpp"/>
@ -1627,7 +1626,6 @@
<ClInclude Include="..\..\Source\Utility\Helpers\jucer_ValueSourceHelpers.h"/>
<ClInclude Include="..\..\Source\Utility\PIPs\jucer_PIPGenerator.h"/>
<ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_ColourPropertyComponent.h"/>
<ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_DependencyPathPropertyComponent.h"/>
<ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_FilePathPropertyComponent.h"/>
<ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_PropertyComponentsWithEnablement.h"/>
<ClInclude Include="..\..\Source\Utility\UI\jucer_IconButton.h"/>

View file

@ -496,9 +496,6 @@
<ClCompile Include="..\..\Source\Utility\PIPs\jucer_PIPGenerator.cpp">
<Filter>Projucer\Utility\PIPs</Filter>
</ClCompile>
<ClCompile Include="..\..\Source\Utility\UI\PropertyComponents\jucer_DependencyPathPropertyComponent.cpp">
<Filter>Projucer\Utility\UI\PropertyComponents</Filter>
</ClCompile>
<ClCompile Include="..\..\Source\Utility\UI\jucer_Icons.cpp">
<Filter>Projucer\Utility\UI</Filter>
</ClCompile>
@ -2325,9 +2322,6 @@
<ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_ColourPropertyComponent.h">
<Filter>Projucer\Utility\UI\PropertyComponents</Filter>
</ClInclude>
<ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_DependencyPathPropertyComponent.h">
<Filter>Projucer\Utility\UI\PropertyComponents</Filter>
</ClInclude>
<ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_FilePathPropertyComponent.h">
<Filter>Projucer\Utility\UI\PropertyComponents</Filter>
</ClInclude>

View file

@ -242,7 +242,6 @@
<ClCompile Include="..\..\Source\Utility\Helpers\jucer_FileHelpers.cpp"/>
<ClCompile Include="..\..\Source\Utility\Helpers\jucer_MiscUtilities.cpp"/>
<ClCompile Include="..\..\Source\Utility\PIPs\jucer_PIPGenerator.cpp"/>
<ClCompile Include="..\..\Source\Utility\UI\PropertyComponents\jucer_DependencyPathPropertyComponent.cpp"/>
<ClCompile Include="..\..\Source\Utility\UI\jucer_Icons.cpp"/>
<ClCompile Include="..\..\Source\Utility\UI\jucer_JucerTreeViewBase.cpp"/>
<ClCompile Include="..\..\Source\Utility\UI\jucer_ProjucerLookAndFeel.cpp"/>
@ -1629,7 +1628,6 @@
<ClInclude Include="..\..\Source\Utility\Helpers\jucer_ValueSourceHelpers.h"/>
<ClInclude Include="..\..\Source\Utility\PIPs\jucer_PIPGenerator.h"/>
<ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_ColourPropertyComponent.h"/>
<ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_DependencyPathPropertyComponent.h"/>
<ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_FilePathPropertyComponent.h"/>
<ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_PropertyComponentsWithEnablement.h"/>
<ClInclude Include="..\..\Source\Utility\UI\jucer_IconButton.h"/>

View file

@ -496,9 +496,6 @@
<ClCompile Include="..\..\Source\Utility\PIPs\jucer_PIPGenerator.cpp">
<Filter>Projucer\Utility\PIPs</Filter>
</ClCompile>
<ClCompile Include="..\..\Source\Utility\UI\PropertyComponents\jucer_DependencyPathPropertyComponent.cpp">
<Filter>Projucer\Utility\UI\PropertyComponents</Filter>
</ClCompile>
<ClCompile Include="..\..\Source\Utility\UI\jucer_Icons.cpp">
<Filter>Projucer\Utility\UI</Filter>
</ClCompile>
@ -2325,9 +2322,6 @@
<ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_ColourPropertyComponent.h">
<Filter>Projucer\Utility\UI\PropertyComponents</Filter>
</ClInclude>
<ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_DependencyPathPropertyComponent.h">
<Filter>Projucer\Utility\UI\PropertyComponents</Filter>
</ClInclude>
<ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_FilePathPropertyComponent.h">
<Filter>Projucer\Utility\UI\PropertyComponents</Filter>
</ClInclude>

View file

@ -655,10 +655,6 @@
<GROUP id="{FE8C76CF-7C05-EC86-8997-C9941B88670B}" name="PropertyComponents">
<FILE id="eleFsw" name="jucer_ColourPropertyComponent.h" compile="0"
resource="0" file="Source/Utility/UI/PropertyComponents/jucer_ColourPropertyComponent.h"/>
<FILE id="D0OfLg" name="jucer_DependencyPathPropertyComponent.cpp"
compile="1" resource="0" file="Source/Utility/UI/PropertyComponents/jucer_DependencyPathPropertyComponent.cpp"/>
<FILE id="gcbJOL" name="jucer_DependencyPathPropertyComponent.h" compile="0"
resource="0" file="Source/Utility/UI/PropertyComponents/jucer_DependencyPathPropertyComponent.h"/>
<FILE id="sfUzaf" name="jucer_FilePathPropertyComponent.h" compile="0"
resource="0" file="Source/Utility/UI/PropertyComponents/jucer_FilePathPropertyComponent.h"/>
<FILE id="DkLOIQ" name="jucer_PropertyComponentsWithEnablement.h" compile="0"

View file

@ -1,280 +0,0 @@
/*
==============================================================================
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 "../../../Application/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 (auto* label = dynamic_cast<Label*> (getChildComponent (0)))
label->onEditorShow = [this, label] { setEditorText (label); };
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::setEditorText (Label* label)
{
if (! pathValueSource.isUsingProjectSettings())
if (auto editor = label->getCurrentTextEditor())
editor->setText (String(), dontSendNotification);
}
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->onEditorShow = [this, label] { setEditorText (label); };
else
jassertfalse;
setInterestedInFileDrag (false);
addAndMakeVisible (browseButton);
browseButton.onClick = [this] { browse(); };
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::setEditorText (Label* label)
{
if (! pathValueSource.isUsingProjectSettings())
if (auto editor = label->getCurrentTextEditor())
editor->setText (String(), dontSendNotification);
}
void DependencyFilePathPropertyComponent::browse()
{
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);
}

View file

@ -1,238 +0,0 @@
/*
==============================================================================
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.
==============================================================================
*/
#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.getValue();
}
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;
Identifier getKey() { return globalKey; }
Value getGlobalSettingsValue() { return globalSettingsValue; }
Value getFallbackSettingsValue() { return fallbackValue; }
private:
void valueChanged (Value& value) override
{
if ((value.refersToSameSourceAs (globalSettingsValue) && isUsingGlobalSettings())
|| (value.refersToSameSourceAs (fallbackValue) && isUsingFallbackValue()))
{
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. */
Value fallbackValue;
};
//==============================================================================
class DependencyPathPropertyComponent : public TextPropertyComponent,
private Value::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;
void setEditorText (Label* label);
void lookAndFeelChanged() override;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DependencyPathPropertyComponent)
};
//==============================================================================
class DependencyFilePathPropertyComponent : public TextPropertyComponent,
public FileDragAndDropTarget,
private Value::Listener
{
public:
DependencyFilePathPropertyComponent (Value& value,
const String& propertyDescription,
bool isDirectory,
const String& wildcards = "*",
const File& rootToUseForRelativePaths = File());
void resized() override;
void paintOverChildren (Graphics& g) override;
bool isInterestedInFileDrag (const StringArray&) override { return isEnabled(); }
void fileDragEnter (const StringArray&, int, int) override { highlightForDragAndDrop = true; repaint(); }
void fileDragExit (const StringArray&) override { highlightForDragAndDrop = false; repaint(); }
void filesDropped (const StringArray&, int, int) override;
void setTo (const File& f);
void enablementChanged() override;
private:
void textWasEdited() override;
void valueChanged (Value&) override;
void setEditorText (Label* label);
void lookAndFeelChanged() override
{
browseButton.setColour (TextButton::buttonColourId,
findColour (secondaryButtonBackgroundColourId));
textWasEdited();
}
void browse();
Colour getTextColourToDisplay() const;
//==========================================================================
File pathRelativeTo;
Value pathValue;
DependencyPathValueSource& pathValueSource;
TextButton browseButton;
bool isDirectory, highlightForDragAndDrop = false;
String wildcards;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DependencyFilePathPropertyComponent)
};

View file

@ -28,193 +28,178 @@
//==============================================================================
class FilePathPropertyComponent : public PropertyComponent
/** A PropertyComponent for selecting files or folders.
The user may drag files over the property box, enter the path manually and/or click
the '...' button to open a file selection dialog box.
*/
class FilePathPropertyComponent : public PropertyComponent,
public FileDragAndDropTarget,
private Value::Listener
{
public:
/** A Property Component for selecting files or folders.
The user may drag files over the property box, enter the path
manually and/or click the '...' button to open a file selection
dialog box
*/
FilePathPropertyComponent (Value valueToControl,
const String& propertyDescription,
bool isDirectory,
const String& wildcards = "*",
const File& rootToUseForRelativePaths = File(),
const bool supportsMultiplePaths = false)
: PropertyComponent (propertyDescription),
innerComp (valueToControl, isDirectory, wildcards, rootToUseForRelativePaths, supportsMultiplePaths)
FilePathPropertyComponent (Value valueToControl, const String& propertyName, bool isDir, bool thisOS = true,
const String& wildcardsToUse = "*", const File& relativeRoot = File(), bool multiPath = false)
: PropertyComponent (propertyName),
text (valueToControl, propertyName, 1024, false),
isDirectory (isDir), isThisOS (thisOS), supportsMultiplePaths (multiPath), wildcards (wildcardsToUse), root (relativeRoot)
{
addAndMakeVisible (innerComp);
textValue.referTo (valueToControl);
init();
}
void refresh() override {} // N/A
/** Displays a default value when no value is specified by the user. */
FilePathPropertyComponent (ValueWithDefault& valueToControl, const String& propertyName, bool isDir, bool thisOS = true,
const String& wildcardsToUse = "*", const File& relativeRoot = File(), bool multiPath = false)
: PropertyComponent (propertyName),
text (valueToControl, propertyName, 1024, false),
isDirectory (isDir), isThisOS (thisOS), supportsMultiplePaths (multiPath), wildcards (wildcardsToUse), root (relativeRoot)
{
textValue = valueToControl.getPropertyAsValue();
init();
}
//==============================================================================
void refresh() override {}
void resized() override
{
auto bounds = getLocalBounds();
browseButton.setBounds (bounds.removeFromRight (50).reduced (5, 0));
text.setBounds (bounds);
}
void paintOverChildren (Graphics& g) override
{
if (highlightForDragAndDrop)
{
g.setColour (findColour (defaultHighlightColourId).withAlpha (0.5f));
g.fillRect (text.getBounds().withTrimmedRight (50));
}
}
//==============================================================================
bool isInterestedInFileDrag (const StringArray&) override { return true; }
void fileDragEnter (const StringArray&, int, int) override { highlightForDragAndDrop = true; repaint(); }
void fileDragExit (const StringArray&) override { highlightForDragAndDrop = false; repaint(); }
void filesDropped (const StringArray& selectedFiles, int, int) override
{
if (supportsMultiplePaths)
{
for (auto& f : selectedFiles)
setTo (f);
}
else
{
setTo (selectedFiles[0]);
}
highlightForDragAndDrop = false;
repaint();
}
private:
struct InnerComponent : public Component,
public FileDragAndDropTarget
//==============================================================================
void init()
{
InnerComponent (Value v, bool isDir, const String& wc, const File& rt, const bool multiplePaths)
: value (v),
isDirectory (isDir),
highlightForDragAndDrop (false),
wildcards (wc),
root (rt),
button ("..."),
supportsMultiplePaths (multiplePaths)
textValue.addListener (this);
text.setInterestedInFileDrag (false);
addAndMakeVisible (text);
browseButton.onClick = [this] { browse(); };
addAndMakeVisible (browseButton);
lookAndFeelChanged();
}
void setTo (File f)
{
if (isDirectory && ! f.isDirectory())
f = f.getParentDirectory();
auto pathName = (root == File()) ? f.getFullPathName()
: f.getRelativePathFrom (root);
auto currentPath = text.getText();
if (supportsMultiplePaths && currentPath.isNotEmpty())
pathName = currentPath.trimCharactersAtEnd (" ;") + "; " + pathName;
text.setText (pathName);
updateEditorColour();
}
void browse()
{
auto currentFile = root.getChildFile (text.getText());
if (isDirectory)
{
addAndMakeVisible (textbox);
textbox.getTextValue().referTo (value);
textbox.onReturnKey = [this] { updateEditorColour (textbox); };
textbox.onFocusLost = [this] { updateEditorColour (textbox); };
FileChooser chooser ("Select directory", currentFile);
addAndMakeVisible (button);
button.onClick = [this] { browse(); };
lookAndFeelChanged();
if (chooser.browseForDirectory())
setTo (chooser.getResult());
}
void paintOverChildren (Graphics& g) override
else
{
if (highlightForDragAndDrop)
{
g.setColour (findColour (defaultHighlightColourId).withAlpha (0.5f));
g.fillRect (textbox.getBounds());
}
}
FileChooser chooser ("Select file", currentFile, wildcards);
void resized() override
if (chooser.browseForFileToOpen())
setTo (chooser.getResult());
}
}
void updateEditorColour()
{
if (supportsMultiplePaths || ! isThisOS)
return;
text.setColour (TextPropertyComponent::textColourId, findColour (widgetTextColourId));
auto pathToCheck = text.getText();
if (pathToCheck.isNotEmpty())
{
juce::Rectangle<int> r (getLocalBounds());
pathToCheck.replace ("${user.home}", "~");
button.setBounds (r.removeFromRight (30));
textbox.setBounds (r);
#if JUCE_WINDOWS
if (pathToCheck.startsWith ("~"))
pathToCheck = pathToCheck.replace ("~", File::getSpecialLocation (File::userHomeDirectory).getFullPathName());
#endif
if (! root.getChildFile (pathToCheck).exists())
text.setColour (TextPropertyComponent::textColourId, Colours::red);
}
}
bool isInterestedInFileDrag (const StringArray&) override { return true; }
void fileDragEnter (const StringArray&, int, int) override { highlightForDragAndDrop = true; repaint(); }
void fileDragExit (const StringArray&) override { highlightForDragAndDrop = false; repaint(); }
void valueChanged (Value&) override
{
updateEditorColour();
}
void filesDropped (const StringArray& files, int, int) override
{
const File firstFile (files[0]);
void lookAndFeelChanged() override
{
browseButton.setColour (TextButton::buttonColourId, findColour (secondaryButtonBackgroundColourId));
browseButton.setColour (TextButton::textColourOffId, Colours::white);
if (isDirectory)
setTo (firstFile.isDirectory() ? firstFile
: firstFile.getParentDirectory());
else
setTo (firstFile);
updateEditorColour();
}
highlightForDragAndDrop = false;
repaint();
}
//==============================================================================
Value textValue;
void browse()
{
auto currentFile = root.getChildFile (value.toString());
TextPropertyComponent text;
TextButton browseButton { "..." };
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());
}
}
void updateEditorColour (TextEditor& editor)
{
if (supportsMultiplePaths)
{
auto paths = StringArray::fromTokens (editor.getTextValue().toString(), ";", {});
editor.clear();
AttributedString str;
for (auto p : paths)
{
if (root.getChildFile (p.trim()).exists()) editor.setColour (TextEditor::textColourId, findColour (widgetTextColourId));
else editor.setColour (TextEditor::textColourId, Colours::red);
editor.insertTextAtCaret (p);
if (paths.indexOf (p) < paths.size() - 1)
{
editor.setColour (TextEditor::textColourId, findColour (widgetTextColourId));
editor.insertTextAtCaret (";");
}
}
editor.setColour (TextEditor::textColourId, findColour (widgetTextColourId));
}
else
{
auto pathToCheck = editor.getTextValue().toString();
if (pathToCheck.isEmpty())
return;
//android SDK/NDK paths
if (pathToCheck.contains ("${user.home}"))
pathToCheck = pathToCheck.replace ("${user.home}", File::getSpecialLocation (File::userHomeDirectory).getFullPathName());
#if JUCE_WINDOWS
if (pathToCheck.startsWith ("~"))
pathToCheck = pathToCheck.replace ("~", File::getSpecialLocation (File::userHomeDirectory).getFullPathName());
#endif
const auto currentFile = root.getChildFile (pathToCheck);
if (currentFile.exists())
editor.applyColourToAllText (findColour (widgetTextColourId));
else
editor.applyColourToAllText (Colours::red);
}
}
void setTo (const File& f)
{
auto pathName = (root == File()) ? f.getFullPathName()
: f.getRelativePathFrom (root);
if (supportsMultiplePaths && value.toString().isNotEmpty())
value = value.toString().trimCharactersAtEnd (" ;") + "; " + pathName;
else
value = pathName;
updateEditorColour (textbox);
}
void lookAndFeelChanged() override
{
textbox.setColour (TextEditor::backgroundColourId, findColour (widgetBackgroundColourId));
textbox.setColour (TextEditor::outlineColourId, Colours::transparentBlack);
updateEditorColour (textbox);
button.setColour (TextButton::buttonColourId, findColour (secondaryButtonBackgroundColourId));
button.setColour (TextButton::textColourOffId, Colours::white);
}
Value value;
bool isDirectory, highlightForDragAndDrop;
String wildcards;
File root;
TextEditor textbox;
TextButton button;
bool supportsMultiplePaths;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (InnerComponent)
};
InnerComponent innerComp; // Used so that the PropertyComponent auto first-child positioning works
bool isDirectory, isThisOS, supportsMultiplePaths, highlightForDragAndDrop = false;
String wildcards;
File root;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FilePathPropertyComponent)
};