diff --git a/extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditor.cpp b/extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditor.cpp index 794dce1994..77f72e77d8 100644 --- a/extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditor.cpp +++ b/extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditor.cpp @@ -701,6 +701,10 @@ private: { mouseDownCompUID = underMouse->getComponentUID(); mouseDownResult = canvas.getSelection().addToSelectionOnMouseDown (mouseDownCompUID, e.mods); + + updateSelectedComponentResizeFrames(); + hideSizeGuides(); + showSizeGuides(); } } } diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index b1e1691420..a7eff1f8c7 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -17620,19 +17620,23 @@ namespace PropertyFileConstants static const char* const valueAttribute = "val"; } -PropertiesFile::PropertiesFile (const File& f, const int millisecondsBeforeSaving, const int options_) +PropertiesFile::PropertiesFile (const File& f, const int millisecondsBeforeSaving, + const int options_, InterProcessLock* const processLock_) : PropertySet (ignoreCaseOfKeyNames), file (f), timerInterval (millisecondsBeforeSaving), options (options_), loadedOk (false), - needsWriting (false) + needsWriting (false), + processLock (processLock_) { // You need to correctly specify just one storage format for the file jassert ((options_ & (storeAsBinary | storeAsCompressedBinary | storeAsXML)) == storeAsBinary || (options_ & (storeAsBinary | storeAsCompressedBinary | storeAsXML)) == storeAsCompressedBinary || (options_ & (storeAsBinary | storeAsCompressedBinary | storeAsXML)) == storeAsXML); + ProcessScopedLock pl (getProcessLock()); + ScopedPointer fileStream (f.createInputStream()); if (fileStream != 0) @@ -17693,8 +17697,10 @@ PropertiesFile::PropertiesFile (const File& f, const int millisecondsBeforeSavin } else { - // must be a pretty broken XML file we're trying to parse here! - jassertfalse + // must be a pretty broken XML file we're trying to parse here, + // or a sign that this object needs an InterProcessLock, + // or just a failure reading the file. This last reason is why + // we don't jassertfalse here. } } } @@ -17711,6 +17717,11 @@ PropertiesFile::~PropertiesFile() jassertfalse; } +PropertiesFile::ProcessScopedLock PropertiesFile::getProcessLock() const +{ + return ProcessScopedLock (processLock != 0 ? new InterProcessLock::ScopedLockType (*processLock) : 0); +} + bool PropertiesFile::saveIfNeeded() { const ScopedLock sl (getLock()); @@ -17760,6 +17771,8 @@ bool PropertiesFile::save() getAllProperties().getAllValues() [i]); } + ProcessScopedLock pl (getProcessLock()); + if (doc.writeToFile (file, String::empty)) { needsWriting = false; @@ -17768,6 +17781,8 @@ bool PropertiesFile::save() } else { + ProcessScopedLock pl (getProcessLock()); + TemporaryFile tempFile (file); ScopedPointer out (tempFile.getFile().createOutputStream()); @@ -17871,7 +17886,8 @@ PropertiesFile* PropertiesFile::createDefaultAppPropertiesFile (const String& ap const String& folderName, const bool commonToAllUsers, const int millisecondsBeforeSaving, - const int propertiesFileOptions) + const int propertiesFileOptions, + InterProcessLock *processLock_) { const File file (getDefaultAppSettingsFile (applicationName, fileNameSuffix, @@ -17883,7 +17899,7 @@ PropertiesFile* PropertiesFile::createDefaultAppPropertiesFile (const String& ap if (file == File::nonexistent) return 0; - return new PropertiesFile (file, millisecondsBeforeSaving, propertiesFileOptions); + return new PropertiesFile (file, millisecondsBeforeSaving, propertiesFileOptions,processLock_); } END_JUCE_NAMESPACE diff --git a/juce_amalgamated.h b/juce_amalgamated.h index 123aae782b..98bb567292 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -13457,7 +13457,8 @@ public: PropertiesFile (const File& file, int millisecondsBeforeSaving, - int optionFlags); + int optionFlags, + InterProcessLock* processLock = 0); ~PropertiesFile(); @@ -13478,7 +13479,8 @@ public: const String& folderName, bool commonToAllUsers, int millisecondsBeforeSaving, - int propertiesFileOptions); + int propertiesFileOptions, + InterProcessLock *ipl = NULL); static const File getDefaultAppSettingsFile (const String& applicationName, const String& fileNameSuffix, @@ -13497,6 +13499,10 @@ private: const int options; bool loadedOk, needsWriting; + InterProcessLock* processLock; + typedef ScopedPointer ProcessScopedLock; + ProcessScopedLock getProcessLock() const; + void timerCallback(); PropertiesFile (const PropertiesFile&); diff --git a/src/utilities/juce_PropertiesFile.cpp b/src/utilities/juce_PropertiesFile.cpp index 22d740c981..1a98714d5c 100644 --- a/src/utilities/juce_PropertiesFile.cpp +++ b/src/utilities/juce_PropertiesFile.cpp @@ -35,7 +35,9 @@ BEGIN_JUCE_NAMESPACE #include "../io/streams/juce_SubregionStream.h" #include "../io/streams/juce_GZIPDecompressorInputStream.h" #include "../io/streams/juce_GZIPCompressorOutputStream.h" +#include "../containers/juce_ScopedPointer.h" #include "../core/juce_SystemStats.h" +#include "../threads/juce_InterProcessLock.h" #include "../text/juce_XmlDocument.h" @@ -52,19 +54,23 @@ namespace PropertyFileConstants } //============================================================================== -PropertiesFile::PropertiesFile (const File& f, const int millisecondsBeforeSaving, const int options_) +PropertiesFile::PropertiesFile (const File& f, const int millisecondsBeforeSaving, + const int options_, InterProcessLock* const processLock_) : PropertySet (ignoreCaseOfKeyNames), file (f), timerInterval (millisecondsBeforeSaving), options (options_), loadedOk (false), - needsWriting (false) + needsWriting (false), + processLock (processLock_) { // You need to correctly specify just one storage format for the file jassert ((options_ & (storeAsBinary | storeAsCompressedBinary | storeAsXML)) == storeAsBinary || (options_ & (storeAsBinary | storeAsCompressedBinary | storeAsXML)) == storeAsCompressedBinary || (options_ & (storeAsBinary | storeAsCompressedBinary | storeAsXML)) == storeAsXML); + ProcessScopedLock pl (getProcessLock()); + ScopedPointer fileStream (f.createInputStream()); if (fileStream != 0) @@ -125,8 +131,10 @@ PropertiesFile::PropertiesFile (const File& f, const int millisecondsBeforeSavin } else { - // must be a pretty broken XML file we're trying to parse here! - jassertfalse + // must be a pretty broken XML file we're trying to parse here, + // or a sign that this object needs an InterProcessLock, + // or just a failure reading the file. This last reason is why + // we don't jassertfalse here. } } } @@ -143,6 +151,11 @@ PropertiesFile::~PropertiesFile() jassertfalse; } +PropertiesFile::ProcessScopedLock PropertiesFile::getProcessLock() const +{ + return ProcessScopedLock (processLock != 0 ? new InterProcessLock::ScopedLockType (*processLock) : 0); +} + bool PropertiesFile::saveIfNeeded() { const ScopedLock sl (getLock()); @@ -192,6 +205,8 @@ bool PropertiesFile::save() getAllProperties().getAllValues() [i]); } + ProcessScopedLock pl (getProcessLock()); + if (doc.writeToFile (file, String::empty)) { needsWriting = false; @@ -200,6 +215,8 @@ bool PropertiesFile::save() } else { + ProcessScopedLock pl (getProcessLock()); + TemporaryFile tempFile (file); ScopedPointer out (tempFile.getFile().createOutputStream()); @@ -304,7 +321,8 @@ PropertiesFile* PropertiesFile::createDefaultAppPropertiesFile (const String& ap const String& folderName, const bool commonToAllUsers, const int millisecondsBeforeSaving, - const int propertiesFileOptions) + const int propertiesFileOptions, + InterProcessLock *processLock_) { const File file (getDefaultAppSettingsFile (applicationName, fileNameSuffix, @@ -316,7 +334,7 @@ PropertiesFile* PropertiesFile::createDefaultAppPropertiesFile (const String& ap if (file == File::nonexistent) return 0; - return new PropertiesFile (file, millisecondsBeforeSaving, propertiesFileOptions); + return new PropertiesFile (file, millisecondsBeforeSaving, propertiesFileOptions,processLock_); } diff --git a/src/utilities/juce_PropertiesFile.h b/src/utilities/juce_PropertiesFile.h index a59e3aafe4..d82da81491 100644 --- a/src/utilities/juce_PropertiesFile.h +++ b/src/utilities/juce_PropertiesFile.h @@ -30,6 +30,7 @@ #include "../containers/juce_PropertySet.h" #include "../events/juce_Timer.h" #include "../events/juce_ChangeBroadcaster.h" +#include "../threads/juce_InterProcessLock.h" //============================================================================== @@ -76,10 +77,17 @@ public: @param optionFlags a combination of the flags in the FileFormatOptions enum, which specify the type of file to save, and other options. + @param processLock an optional InterprocessLock object that will be used to + prevent multiple threads or processes from writing to the file + at the same time. The PropertiesFile will keep a pointer to + this object but will not take ownership of it - the caller is + responsible for making sure that the lock doesn't get deleted + before the PropertiesFile has been deleted. */ PropertiesFile (const File& file, int millisecondsBeforeSaving, - int optionFlags); + int optionFlags, + InterProcessLock* processLock = 0); /** Destructor. @@ -146,7 +154,8 @@ public: const String& folderName, bool commonToAllUsers, int millisecondsBeforeSaving, - int propertiesFileOptions); + int propertiesFileOptions, + InterProcessLock *ipl = NULL); /** Handy utility to choose a file in the standard OS-dependent location for application settings files. @@ -187,6 +196,10 @@ private: const int options; bool loadedOk, needsWriting; + InterProcessLock* processLock; + typedef ScopedPointer ProcessScopedLock; + ProcessScopedLock getProcessLock() const; + void timerCallback(); PropertiesFile (const PropertiesFile&);