@@ -701,6 +701,10 @@ private: | |||
{ | |||
mouseDownCompUID = underMouse->getComponentUID(); | |||
mouseDownResult = canvas.getSelection().addToSelectionOnMouseDown (mouseDownCompUID, e.mods); | |||
updateSelectedComponentResizeFrames(); | |||
hideSizeGuides(); | |||
showSizeGuides(); | |||
} | |||
} | |||
} | |||
@@ -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<InputStream> 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 <OutputStream> 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 | |||
@@ -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<InterProcessLock::ScopedLockType> ProcessScopedLock; | |||
ProcessScopedLock getProcessLock() const; | |||
void timerCallback(); | |||
PropertiesFile (const PropertiesFile&); | |||
@@ -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<InputStream> 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 <OutputStream> 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_); | |||
} | |||
@@ -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<InterProcessLock::ScopedLockType> ProcessScopedLock; | |||
ProcessScopedLock getProcessLock() const; | |||
void timerCallback(); | |||
PropertiesFile (const PropertiesFile&); | |||