@@ -40,8 +40,6 @@ | |||||
extern ApplicationCommandManager* commandManager; | extern ApplicationCommandManager* commandManager; | ||||
//============================================================================== | //============================================================================== | ||||
static const char* const newLine = "\r\n"; | |||||
const char* const projectItemDragType = "Project Items"; | const char* const projectItemDragType = "Project Items"; | ||||
const char* const drawableItemDragType = "Drawable Items"; | const char* const drawableItemDragType = "Drawable Items"; | ||||
const char* const componentItemDragType = "Components"; | const char* const componentItemDragType = "Components"; | ||||
@@ -523,7 +523,7 @@ public: | |||||
protected: | protected: | ||||
virtual const String getProjectVersionString() const { return "9.00"; } | virtual const String getProjectVersionString() const { return "9.00"; } | ||||
virtual const String getSolutionVersionString() const { return String ("10.00") + newLine + "# Visual C++ Express 2008"; } | |||||
virtual const String getSolutionVersionString() const { return "10.00" + newLine + "# Visual C++ Express 2008"; } | |||||
const File getVCProjFile() const { return getProjectFile (".vcproj"); } | const File getVCProjFile() const { return getProjectFile (".vcproj"); } | ||||
const File getSLNFile() const { return getProjectFile (".sln"); } | const File getSLNFile() const { return getProjectFile (".sln"); } | ||||
@@ -847,7 +847,7 @@ public: | |||||
protected: | protected: | ||||
const String getProjectVersionString() const { return "8.00"; } | const String getProjectVersionString() const { return "8.00"; } | ||||
const String getSolutionVersionString() const { return String ("8.00") + newLine + "# Visual C++ Express 2005"; } | |||||
const String getSolutionVersionString() const { return "8.00" + newLine + "# Visual C++ Express 2005"; } | |||||
JUCE_DECLARE_NON_COPYABLE (MSVCProjectExporterVC2005); | JUCE_DECLARE_NON_COPYABLE (MSVCProjectExporterVC2005); | ||||
}; | }; | ||||
@@ -1227,10 +1227,10 @@ FileLogger::FileLogger (const File& logFile_, | |||||
} | } | ||||
String welcome; | String welcome; | ||||
welcome << "\r\n**********************************************************\r\n" | |||||
<< welcomeMessage | |||||
<< "\r\nLog started: " << Time::getCurrentTime().toString (true, true) | |||||
<< "\r\n"; | |||||
welcome << newLine | |||||
<< "**********************************************************" << newLine | |||||
<< welcomeMessage << newLine | |||||
<< "Log started: " << Time::getCurrentTime().toString (true, true) << newLine; | |||||
logMessage (welcome); | logMessage (welcome); | ||||
} | } | ||||
@@ -1246,7 +1246,7 @@ void FileLogger::logMessage (const String& message) | |||||
const ScopedLock sl (logLock); | const ScopedLock sl (logLock); | ||||
FileOutputStream out (logFile, 256); | FileOutputStream out (logFile, 256); | ||||
out << message << "\r\n"; | |||||
out << message << newLine; | |||||
} | } | ||||
void FileLogger::trimFileSize (int maxFileSizeBytes) const | void FileLogger::trimFileSize (int maxFileSizeBytes) const | ||||
@@ -6745,6 +6745,7 @@ void juce_CheckForDanglingStreams() | |||||
#endif | #endif | ||||
OutputStream::OutputStream() | OutputStream::OutputStream() | ||||
: newLineString (NewLine::getDefault()) | |||||
{ | { | ||||
#if JUCE_DEBUG | #if JUCE_DEBUG | ||||
activeStreams.add (this); | activeStreams.add (this); | ||||
@@ -6942,6 +6943,11 @@ int OutputStream::writeFromInputStream (InputStream& source, int64 numBytesToWri | |||||
return numWritten; | return numWritten; | ||||
} | } | ||||
void OutputStream::setNewLineString (const String& newLineString_) | |||||
{ | |||||
newLineString = newLineString_; | |||||
} | |||||
OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const int number) | OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const int number) | ||||
{ | { | ||||
return stream << String (number); | return stream << String (number); | ||||
@@ -6980,6 +6986,11 @@ OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const File& fileTo | |||||
return stream; | return stream; | ||||
} | } | ||||
OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const NewLine&) | |||||
{ | |||||
return stream << stream.getNewLineString(); | |||||
} | |||||
END_JUCE_NAMESPACE | END_JUCE_NAMESPACE | ||||
/*** End of inlined file: juce_OutputStream.cpp ***/ | /*** End of inlined file: juce_OutputStream.cpp ***/ | ||||
@@ -10175,7 +10186,7 @@ PerformanceCounter::PerformanceCounter (const String& name_, | |||||
String s ("**** Counter for \""); | String s ("**** Counter for \""); | ||||
s << name_ << "\" started at: " | s << name_ << "\" started at: " | ||||
<< Time::getCurrentTime().toString (true, true) | << Time::getCurrentTime().toString (true, true) | ||||
<< "\r\n"; | |||||
<< newLine; | |||||
outputFile.appendText (s, false, false); | outputFile.appendText (s, false, false); | ||||
} | } | ||||
@@ -10219,7 +10230,7 @@ void PerformanceCounter::printStatistics() | |||||
Logger::outputDebugString (s); | Logger::outputDebugString (s); | ||||
s << "\r\n"; | |||||
s << newLine; | |||||
if (outputFile != File::nonexistent) | if (outputFile != File::nonexistent) | ||||
outputFile.appendText (s, false, false); | outputFile.appendText (s, false, false); | ||||
@@ -11656,6 +11667,8 @@ BEGIN_JUCE_NAMESPACE | |||||
#error "JUCE_STRINGS_ARE_UNICODE is deprecated! All strings are now unicode by default." | #error "JUCE_STRINGS_ARE_UNICODE is deprecated! All strings are now unicode by default." | ||||
#endif | #endif | ||||
NewLine newLine; | |||||
class StringHolder | class StringHolder | ||||
{ | { | ||||
public: | public: | ||||
@@ -12376,6 +12389,11 @@ JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const Str | |||||
return stream; | return stream; | ||||
} | } | ||||
JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, const NewLine&) | |||||
{ | |||||
return string1 += NewLine::getDefault(); | |||||
} | |||||
int String::indexOfChar (const juce_wchar character) const throw() | int String::indexOfChar (const juce_wchar character) const throw() | ||||
{ | { | ||||
const juce_wchar* t = text; | const juce_wchar* t = text; | ||||
@@ -15819,11 +15837,6 @@ namespace XmlOutputFunctions | |||||
out.write (blanks, numSpaces); | out.write (blanks, numSpaces); | ||||
} | } | ||||
} | } | ||||
void writeNewLine (OutputStream& out) | |||||
{ | |||||
out.write ("\r\n", 2); | |||||
} | |||||
} | } | ||||
void XmlElement::writeElementAsText (OutputStream& outputStream, | void XmlElement::writeElementAsText (OutputStream& outputStream, | ||||
@@ -15846,7 +15859,7 @@ void XmlElement::writeElementAsText (OutputStream& outputStream, | |||||
{ | { | ||||
if (lineLen > lineWrapLength && indentationLevel >= 0) | if (lineLen > lineWrapLength && indentationLevel >= 0) | ||||
{ | { | ||||
writeNewLine (outputStream); | |||||
outputStream << newLine; | |||||
writeSpaces (outputStream, attIndent); | writeSpaces (outputStream, attIndent); | ||||
lineLen = 0; | lineLen = 0; | ||||
} | } | ||||
@@ -15878,7 +15891,7 @@ void XmlElement::writeElementAsText (OutputStream& outputStream, | |||||
else | else | ||||
{ | { | ||||
if (indentationLevel >= 0 && ! lastWasTextNode) | if (indentationLevel >= 0 && ! lastWasTextNode) | ||||
writeNewLine (outputStream); | |||||
outputStream << newLine; | |||||
child->writeElementAsText (outputStream, | child->writeElementAsText (outputStream, | ||||
lastWasTextNode ? 0 : (indentationLevel + (indentationLevel >= 0 ? 2 : 0)), lineWrapLength); | lastWasTextNode ? 0 : (indentationLevel + (indentationLevel >= 0 ? 2 : 0)), lineWrapLength); | ||||
@@ -15890,7 +15903,7 @@ void XmlElement::writeElementAsText (OutputStream& outputStream, | |||||
if (indentationLevel >= 0 && ! lastWasTextNode) | if (indentationLevel >= 0 && ! lastWasTextNode) | ||||
{ | { | ||||
writeNewLine (outputStream); | |||||
outputStream << newLine; | |||||
writeSpaces (outputStream, indentationLevel); | writeSpaces (outputStream, indentationLevel); | ||||
} | } | ||||
@@ -15935,14 +15948,9 @@ void XmlElement::writeToStream (OutputStream& output, | |||||
output << "<?xml version=\"1.0\" encoding=\"" << encodingType << "\"?>"; | output << "<?xml version=\"1.0\" encoding=\"" << encodingType << "\"?>"; | ||||
if (allOnOneLine) | if (allOnOneLine) | ||||
{ | |||||
output.writeByte (' '); | output.writeByte (' '); | ||||
} | |||||
else | else | ||||
{ | |||||
writeNewLine (output); | |||||
writeNewLine (output); | |||||
} | |||||
output << newLine << newLine; | |||||
} | } | ||||
if (dtdToUse.isNotEmpty()) | if (dtdToUse.isNotEmpty()) | ||||
@@ -15952,13 +15960,13 @@ void XmlElement::writeToStream (OutputStream& output, | |||||
if (allOnOneLine) | if (allOnOneLine) | ||||
output.writeByte (' '); | output.writeByte (' '); | ||||
else | else | ||||
writeNewLine (output); | |||||
output << newLine; | |||||
} | } | ||||
writeElementAsText (output, allOnOneLine ? -1 : 0, lineWrapLength); | writeElementAsText (output, allOnOneLine ? -1 : 0, lineWrapLength); | ||||
if (! allOnOneLine) | if (! allOnOneLine) | ||||
writeNewLine (output); | |||||
output << newLine; | |||||
} | } | ||||
bool XmlElement::writeToFile (const File& file, | bool XmlElement::writeToFile (const File& file, | ||||
@@ -44121,33 +44129,34 @@ void DrawableButton::resized() | |||||
{ | { | ||||
Button::resized(); | Button::resized(); | ||||
if (style == ImageRaw) | |||||
{ | |||||
currentImage->setOriginWithOriginalSize (Point<float>()); | |||||
} | |||||
else if (currentImage != 0) | |||||
if (currentImage != 0) | |||||
{ | { | ||||
Rectangle<int> imageSpace; | |||||
if (style == ImageOnButtonBackground) | |||||
if (style == ImageRaw) | |||||
{ | { | ||||
imageSpace = getLocalBounds().reduced (getWidth() / 4, getHeight() / 4); | |||||
currentImage->setOriginWithOriginalSize (Point<float>()); | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
const int textH = (style == ImageAboveTextLabel) | |||||
? jmin (16, proportionOfHeight (0.25f)) | |||||
: 0; | |||||
Rectangle<int> imageSpace; | |||||
if (style == ImageOnButtonBackground) | |||||
{ | |||||
imageSpace = getLocalBounds().reduced (getWidth() / 4, getHeight() / 4); | |||||
} | |||||
else | |||||
{ | |||||
const int textH = (style == ImageAboveTextLabel) ? jmin (16, proportionOfHeight (0.25f)) : 0; | |||||
const int indentX = jmin (edgeIndent, proportionOfWidth (0.3f)); | |||||
const int indentY = jmin (edgeIndent, proportionOfHeight (0.3f)); | |||||
const int indentX = jmin (edgeIndent, proportionOfWidth (0.3f)); | |||||
const int indentY = jmin (edgeIndent, proportionOfHeight (0.3f)); | |||||
imageSpace.setBounds (indentX, indentY, | |||||
getWidth() - indentX * 2, | |||||
getHeight() - indentY * 2 - textH); | |||||
} | |||||
imageSpace.setBounds (indentX, indentY, | |||||
getWidth() - indentX * 2, | |||||
getHeight() - indentY * 2 - textH); | |||||
} | |||||
currentImage->setTransformToFit (imageSpace.toFloat(), RectanglePlacement::centred); | |||||
currentImage->setTransformToFit (imageSpace.toFloat(), RectanglePlacement::centred); | |||||
} | |||||
} | } | ||||
} | } | ||||
@@ -64923,7 +64932,6 @@ LookAndFeel::LookAndFeel() | |||||
ScrollBar::backgroundColourId, 0x00000000, | ScrollBar::backgroundColourId, 0x00000000, | ||||
ScrollBar::thumbColourId, 0xffffffff, | ScrollBar::thumbColourId, 0xffffffff, | ||||
ScrollBar::trackColourId, 0xffffffff, | |||||
TreeView::linesColourId, 0x4c000000, | TreeView::linesColourId, 0x4c000000, | ||||
TreeView::backgroundColourId, 0x00000000, | TreeView::backgroundColourId, 0x00000000, | ||||
@@ -65583,9 +65591,20 @@ void LookAndFeel::drawScrollbar (Graphics& g, | |||||
} | } | ||||
const Colour thumbColour (scrollbar.findColour (ScrollBar::thumbColourId)); | const Colour thumbColour (scrollbar.findColour (ScrollBar::thumbColourId)); | ||||
Colour trackColour1, trackColour2; | |||||
g.setGradientFill (ColourGradient (thumbColour.overlaidWith (Colour (0x44000000)), gx1, gy1, | |||||
thumbColour.overlaidWith (Colour (0x19000000)), gx2, gy2, false)); | |||||
if (scrollbar.isColourSpecified (ScrollBar::trackColourId)) | |||||
{ | |||||
trackColour1 = trackColour2 = scrollbar.findColour (ScrollBar::trackColourId); | |||||
} | |||||
else | |||||
{ | |||||
trackColour1 = thumbColour.overlaidWith (Colour (0x44000000)); | |||||
trackColour2 = thumbColour.overlaidWith (Colour (0x19000000)); | |||||
} | |||||
g.setGradientFill (ColourGradient (trackColour1, gx1, gy1, | |||||
trackColour2, gx2, gy2, false)); | |||||
g.fillPath (slotPath); | g.fillPath (slotPath); | ||||
if (isScrollbarVertical) | if (isScrollbarVertical) | ||||
@@ -74513,45 +74532,30 @@ BEGIN_JUCE_NAMESPACE | |||||
class ShadowWindow : public Component | class ShadowWindow : public Component | ||||
{ | { | ||||
Component* owner; | |||||
Image shadowImageSections [12]; | |||||
const int type; // 0 = left, 1 = right, 2 = top, 3 = bottom. left + right are full-height | |||||
public: | public: | ||||
ShadowWindow (Component* const owner_, | |||||
const int type_, | |||||
const Image shadowImageSections_ [12]) | |||||
: owner (owner_), | |||||
ShadowWindow (Component& owner, const int type_, const Image shadowImageSections [12]) | |||||
: topLeft (shadowImageSections [type_ * 3]), | |||||
bottomRight (shadowImageSections [type_ * 3 + 1]), | |||||
filler (shadowImageSections [type_ * 3 + 2]), | |||||
type (type_) | type (type_) | ||||
{ | { | ||||
for (int i = 0; i < numElementsInArray (shadowImageSections); ++i) | |||||
shadowImageSections [i] = shadowImageSections_ [i]; | |||||
setInterceptsMouseClicks (false, false); | setInterceptsMouseClicks (false, false); | ||||
if (owner_->isOnDesktop()) | |||||
if (owner.isOnDesktop()) | |||||
{ | { | ||||
setSize (1, 1); // to keep the OS happy by not having zero-size windows | setSize (1, 1); // to keep the OS happy by not having zero-size windows | ||||
addToDesktop (ComponentPeer::windowIgnoresMouseClicks | addToDesktop (ComponentPeer::windowIgnoresMouseClicks | ||||
| ComponentPeer::windowIsTemporary | | ComponentPeer::windowIsTemporary | ||||
| ComponentPeer::windowIgnoresKeyPresses); | | ComponentPeer::windowIgnoresKeyPresses); | ||||
} | } | ||||
else if (owner_->getParentComponent() != 0) | |||||
else if (owner.getParentComponent() != 0) | |||||
{ | { | ||||
owner_->getParentComponent()->addChildComponent (this); | |||||
owner.getParentComponent()->addChildComponent (this); | |||||
} | } | ||||
} | } | ||||
~ShadowWindow() | |||||
{ | |||||
} | |||||
void paint (Graphics& g) | void paint (Graphics& g) | ||||
{ | { | ||||
const Image& topLeft = shadowImageSections [type * 3]; | |||||
const Image& bottomRight = shadowImageSections [type * 3 + 1]; | |||||
const Image& filler = shadowImageSections [type * 3 + 2]; | |||||
g.setOpacity (1.0f); | g.setOpacity (1.0f); | ||||
if (type < 2) | if (type < 2) | ||||
@@ -74592,6 +74596,9 @@ public: | |||||
} | } | ||||
private: | private: | ||||
const Image topLeft, bottomRight, filler; | |||||
const int type; // 0 = left, 1 = right, 2 = top, 3 = bottom. left + right are full-height | |||||
JUCE_DECLARE_NON_COPYABLE (ShadowWindow); | JUCE_DECLARE_NON_COPYABLE (ShadowWindow); | ||||
}; | }; | ||||
@@ -74600,13 +74607,10 @@ DropShadower::DropShadower (const float alpha_, | |||||
const int yOffset_, | const int yOffset_, | ||||
const float blurRadius_) | const float blurRadius_) | ||||
: owner (0), | : owner (0), | ||||
numShadows (0), | |||||
shadowEdge (jmax (xOffset_, yOffset_) + (int) blurRadius_), | |||||
xOffset (xOffset_), | xOffset (xOffset_), | ||||
yOffset (yOffset_), | yOffset (yOffset_), | ||||
alpha (alpha_), | alpha (alpha_), | ||||
blurRadius (blurRadius_), | blurRadius (blurRadius_), | ||||
inDestructor (false), | |||||
reentrant (false) | reentrant (false) | ||||
{ | { | ||||
} | } | ||||
@@ -74616,21 +74620,8 @@ DropShadower::~DropShadower() | |||||
if (owner != 0) | if (owner != 0) | ||||
owner->removeComponentListener (this); | owner->removeComponentListener (this); | ||||
inDestructor = true; | |||||
deleteShadowWindows(); | |||||
} | |||||
void DropShadower::deleteShadowWindows() | |||||
{ | |||||
if (numShadows > 0) | |||||
{ | |||||
int i; | |||||
for (i = numShadows; --i >= 0;) | |||||
delete shadowWindows[i]; | |||||
numShadows = 0; | |||||
} | |||||
reentrant = true; | |||||
shadowWindows.clear(); | |||||
} | } | ||||
void DropShadower::setOwner (Component* componentToFollow) | void DropShadower::setOwner (Component* componentToFollow) | ||||
@@ -74664,13 +74655,9 @@ void DropShadower::componentBroughtToFront (Component&) | |||||
bringShadowWindowsToFront(); | bringShadowWindowsToFront(); | ||||
} | } | ||||
void DropShadower::componentChildrenChanged (Component&) | |||||
{ | |||||
} | |||||
void DropShadower::componentParentHierarchyChanged (Component&) | void DropShadower::componentParentHierarchyChanged (Component&) | ||||
{ | { | ||||
deleteShadowWindows(); | |||||
shadowWindows.clear(); | |||||
updateShadows(); | updateShadows(); | ||||
} | } | ||||
@@ -74681,23 +74668,23 @@ void DropShadower::componentVisibilityChanged (Component&) | |||||
void DropShadower::updateShadows() | void DropShadower::updateShadows() | ||||
{ | { | ||||
if (reentrant || inDestructor || (owner == 0)) | |||||
if (reentrant || owner == 0) | |||||
return; | return; | ||||
reentrant = true; | reentrant = true; | ||||
ComponentPeer* const nw = owner->getPeer(); | |||||
ComponentPeer* const peer = owner->getPeer(); | |||||
const bool isOwnerVisible = owner->isVisible() && (peer == 0 || ! peer->isMinimised()); | |||||
const bool isOwnerVisible = owner->isVisible() | |||||
&& (nw == 0 || ! nw->isMinimised()); | |||||
const bool createShadowWindows = numShadows == 0 | |||||
const bool createShadowWindows = shadowWindows.size() == 0 | |||||
&& owner->getWidth() > 0 | && owner->getWidth() > 0 | ||||
&& owner->getHeight() > 0 | && owner->getHeight() > 0 | ||||
&& isOwnerVisible | && isOwnerVisible | ||||
&& (Desktop::canUseSemiTransparentWindows() | && (Desktop::canUseSemiTransparentWindows() | ||||
|| owner->getParentComponent() != 0); | || owner->getParentComponent() != 0); | ||||
const int shadowEdge = jmax (xOffset, yOffset) + (int) blurRadius; | |||||
if (createShadowWindows) | if (createShadowWindows) | ||||
{ | { | ||||
// keep a cached version of the image to save doing the gaussian too often | // keep a cached version of the image to save doing the gaussian too often | ||||
@@ -74747,18 +74734,15 @@ void DropShadower::updateShadows() | |||||
setShadowImage (bigIm, 11, shadowEdge, shadowEdge, shadowEdge2, ih - shadowEdge); | setShadowImage (bigIm, 11, shadowEdge, shadowEdge, shadowEdge2, ih - shadowEdge); | ||||
for (int i = 0; i < 4; ++i) | for (int i = 0; i < 4; ++i) | ||||
{ | |||||
shadowWindows[numShadows] = new ShadowWindow (owner, i, shadowImageSections); | |||||
++numShadows; | |||||
} | |||||
shadowWindows.add (new ShadowWindow (*owner, i, shadowImageSections)); | |||||
} | } | ||||
if (numShadows > 0) | |||||
if (shadowWindows.size() >= 4) | |||||
{ | { | ||||
for (int i = numShadows; --i >= 0;) | |||||
for (int i = shadowWindows.size(); --i >= 0;) | |||||
{ | { | ||||
shadowWindows[i]->setAlwaysOnTop (owner->isAlwaysOnTop()); | |||||
shadowWindows[i]->setVisible (isOwnerVisible); | |||||
shadowWindows.getUnchecked(i)->setAlwaysOnTop (owner->isAlwaysOnTop()); | |||||
shadowWindows.getUnchecked(i)->setVisible (isOwnerVisible); | |||||
} | } | ||||
const int x = owner->getX(); | const int x = owner->getX(); | ||||
@@ -74766,25 +74750,10 @@ void DropShadower::updateShadows() | |||||
const int w = owner->getWidth(); | const int w = owner->getWidth(); | ||||
const int h = owner->getHeight() + shadowEdge + shadowEdge; | const int h = owner->getHeight() + shadowEdge + shadowEdge; | ||||
shadowWindows[0]->setBounds (x - shadowEdge, | |||||
y, | |||||
shadowEdge, | |||||
h); | |||||
shadowWindows[1]->setBounds (x + w, | |||||
y, | |||||
shadowEdge, | |||||
h); | |||||
shadowWindows[2]->setBounds (x, | |||||
y, | |||||
w, | |||||
shadowEdge); | |||||
shadowWindows[3]->setBounds (x, | |||||
owner->getBottom(), | |||||
w, | |||||
shadowEdge); | |||||
shadowWindows.getUnchecked(0)->setBounds (x - shadowEdge, y, shadowEdge, h); | |||||
shadowWindows.getUnchecked(1)->setBounds (x + w, y, shadowEdge, h); | |||||
shadowWindows.getUnchecked(2)->setBounds (x, y, w, shadowEdge); | |||||
shadowWindows.getUnchecked(3)->setBounds (x, owner->getBottom(), w, shadowEdge); | |||||
} | } | ||||
reentrant = false; | reentrant = false; | ||||
@@ -74804,14 +74773,14 @@ void DropShadower::setShadowImage (const Image& src, const int num, const int w, | |||||
void DropShadower::bringShadowWindowsToFront() | void DropShadower::bringShadowWindowsToFront() | ||||
{ | { | ||||
if (! (inDestructor || reentrant)) | |||||
if (! reentrant) | |||||
{ | { | ||||
updateShadows(); | updateShadows(); | ||||
reentrant = true; | reentrant = true; | ||||
for (int i = numShadows; --i >= 0;) | |||||
shadowWindows[i]->toBehind (owner); | |||||
for (int i = shadowWindows.size(); --i >= 0;) | |||||
shadowWindows.getUnchecked(i)->toBehind (owner); | |||||
reentrant = false; | reentrant = false; | ||||
} | } | ||||
@@ -2804,6 +2804,47 @@ JUCE_API std::basic_ostream <charT, traits>& JUCE_CALLTYPE operator<< (std::basi | |||||
/** Writes a string to an OutputStream as UTF8. */ | /** Writes a string to an OutputStream as UTF8. */ | ||||
JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const String& text); | JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const String& text); | ||||
/** This class is used for represent a new-line character sequence. | |||||
To write a new-line to a stream, you can use the predefined 'newLine' variable, e.g. | |||||
@code | |||||
myOutputStream << "Hello World" << newLine << newLine; | |||||
@endcode | |||||
The exact character sequence that will be used for the new-line can be set and | |||||
retrieved with OutputStream::setNewLineString() and OutputStream::getNewLineString(). | |||||
*/ | |||||
class NewLine | |||||
{ | |||||
public: | |||||
/** Returns the default new-line sequence that the library uses. | |||||
@see OutputStream::setNewLineString() | |||||
*/ | |||||
static const char* getDefault() throw() { return "\r\n"; } | |||||
/** Returns the default new-line sequence that the library uses. | |||||
@see getDefault() | |||||
*/ | |||||
operator const String() const { return getDefault(); } | |||||
}; | |||||
/** An object representing a new-line, which can be written to a string or stream. | |||||
To write a new-line to a stream, you can use the predefined 'newLine' variable like this: | |||||
@code | |||||
myOutputStream << "Hello World" << newLine << newLine; | |||||
@endcode | |||||
*/ | |||||
extern NewLine newLine; | |||||
/** Writes a new-line sequence to a string. | |||||
You can use the predefined object 'newLine' to invoke this, e.g. | |||||
@code | |||||
myString << "Hello World" << newLine << newLine; | |||||
@endcode | |||||
*/ | |||||
JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, const NewLine&); | |||||
#endif // __JUCE_STRING_JUCEHEADER__ | #endif // __JUCE_STRING_JUCEHEADER__ | ||||
/*** End of inlined file: juce_String.h ***/ | /*** End of inlined file: juce_String.h ***/ | ||||
@@ -6235,8 +6276,19 @@ public: | |||||
*/ | */ | ||||
virtual int writeFromInputStream (InputStream& source, int64 maxNumBytesToWrite); | virtual int writeFromInputStream (InputStream& source, int64 maxNumBytesToWrite); | ||||
/** Sets the string that will be written to the stream when the writeNewLine() | |||||
method is called. | |||||
By default this will be set the the value of NewLine::getDefault(). | |||||
*/ | |||||
void setNewLineString (const String& newLineString); | |||||
/** Returns the current new-line string that was set by setNewLineString(). */ | |||||
const String& getNewLineString() const throw() { return newLineString; } | |||||
private: | private: | ||||
String newLineString; | |||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OutputStream); | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OutputStream); | ||||
}; | }; | ||||
@@ -6258,6 +6310,15 @@ OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const MemoryBlock& | |||||
/** Writes the contents of a file to a stream. */ | /** Writes the contents of a file to a stream. */ | ||||
OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const File& fileToRead); | OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const File& fileToRead); | ||||
/** Writes a new-line to a stream. | |||||
You can use the predefined symbol 'newLine' to invoke this, e.g. | |||||
@code | |||||
myOutputStream << "Hello World" << newLine << newLine; | |||||
@endcode | |||||
@see OutputStream::setNewLineString | |||||
*/ | |||||
OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const NewLine&); | |||||
#endif // __JUCE_OUTPUTSTREAM_JUCEHEADER__ | #endif // __JUCE_OUTPUTSTREAM_JUCEHEADER__ | ||||
/*** End of inlined file: juce_OutputStream.h ***/ | /*** End of inlined file: juce_OutputStream.h ***/ | ||||
@@ -50898,8 +50959,6 @@ public: | |||||
/** @internal */ | /** @internal */ | ||||
void componentBroughtToFront (Component& component); | void componentBroughtToFront (Component& component); | ||||
/** @internal */ | /** @internal */ | ||||
void componentChildrenChanged (Component& component); | |||||
/** @internal */ | |||||
void componentParentHierarchyChanged (Component& component); | void componentParentHierarchyChanged (Component& component); | ||||
/** @internal */ | /** @internal */ | ||||
void componentVisibilityChanged (Component& component); | void componentVisibilityChanged (Component& component); | ||||
@@ -50907,17 +50966,15 @@ public: | |||||
private: | private: | ||||
Component* owner; | Component* owner; | ||||
int numShadows; | |||||
Component* shadowWindows[4]; | |||||
OwnedArray<Component> shadowWindows; | |||||
Image shadowImageSections[12]; | Image shadowImageSections[12]; | ||||
const int shadowEdge, xOffset, yOffset; | |||||
const int xOffset, yOffset; | |||||
const float alpha, blurRadius; | const float alpha, blurRadius; | ||||
bool inDestructor, reentrant; | |||||
bool reentrant; | |||||
void updateShadows(); | void updateShadows(); | ||||
void setShadowImage (const Image& src, int num, int w, int h, int sx, int sy); | void setShadowImage (const Image& src, int num, int w, int h, int sx, int sy); | ||||
void bringShadowWindowsToFront(); | void bringShadowWindowsToFront(); | ||||
void deleteShadowWindows(); | |||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DropShadower); | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DropShadower); | ||||
}; | }; | ||||
@@ -51,10 +51,10 @@ FileLogger::FileLogger (const File& logFile_, | |||||
} | } | ||||
String welcome; | String welcome; | ||||
welcome << "\r\n**********************************************************\r\n" | |||||
<< welcomeMessage | |||||
<< "\r\nLog started: " << Time::getCurrentTime().toString (true, true) | |||||
<< "\r\n"; | |||||
welcome << newLine | |||||
<< "**********************************************************" << newLine | |||||
<< welcomeMessage << newLine | |||||
<< "Log started: " << Time::getCurrentTime().toString (true, true) << newLine; | |||||
logMessage (welcome); | logMessage (welcome); | ||||
} | } | ||||
@@ -71,7 +71,7 @@ void FileLogger::logMessage (const String& message) | |||||
const ScopedLock sl (logLock); | const ScopedLock sl (logLock); | ||||
FileOutputStream out (logFile, 256); | FileOutputStream out (logFile, 256); | ||||
out << message << "\r\n"; | |||||
out << message << newLine; | |||||
} | } | ||||
@@ -46,7 +46,7 @@ PerformanceCounter::PerformanceCounter (const String& name_, | |||||
String s ("**** Counter for \""); | String s ("**** Counter for \""); | ||||
s << name_ << "\" started at: " | s << name_ << "\" started at: " | ||||
<< Time::getCurrentTime().toString (true, true) | << Time::getCurrentTime().toString (true, true) | ||||
<< "\r\n"; | |||||
<< newLine; | |||||
outputFile.appendText (s, false, false); | outputFile.appendText (s, false, false); | ||||
} | } | ||||
@@ -90,7 +90,7 @@ void PerformanceCounter::printStatistics() | |||||
Logger::outputDebugString (s); | Logger::outputDebugString (s); | ||||
s << "\r\n"; | |||||
s << newLine; | |||||
if (outputFile != File::nonexistent) | if (outputFile != File::nonexistent) | ||||
outputFile.appendText (s, false, false); | outputFile.appendText (s, false, false); | ||||
@@ -119,33 +119,34 @@ void DrawableButton::resized() | |||||
{ | { | ||||
Button::resized(); | Button::resized(); | ||||
if (style == ImageRaw) | |||||
{ | |||||
currentImage->setOriginWithOriginalSize (Point<float>()); | |||||
} | |||||
else if (currentImage != 0) | |||||
if (currentImage != 0) | |||||
{ | { | ||||
Rectangle<int> imageSpace; | |||||
if (style == ImageOnButtonBackground) | |||||
if (style == ImageRaw) | |||||
{ | { | ||||
imageSpace = getLocalBounds().reduced (getWidth() / 4, getHeight() / 4); | |||||
currentImage->setOriginWithOriginalSize (Point<float>()); | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
const int textH = (style == ImageAboveTextLabel) | |||||
? jmin (16, proportionOfHeight (0.25f)) | |||||
: 0; | |||||
Rectangle<int> imageSpace; | |||||
const int indentX = jmin (edgeIndent, proportionOfWidth (0.3f)); | |||||
const int indentY = jmin (edgeIndent, proportionOfHeight (0.3f)); | |||||
if (style == ImageOnButtonBackground) | |||||
{ | |||||
imageSpace = getLocalBounds().reduced (getWidth() / 4, getHeight() / 4); | |||||
} | |||||
else | |||||
{ | |||||
const int textH = (style == ImageAboveTextLabel) ? jmin (16, proportionOfHeight (0.25f)) : 0; | |||||
imageSpace.setBounds (indentX, indentY, | |||||
getWidth() - indentX * 2, | |||||
getHeight() - indentY * 2 - textH); | |||||
} | |||||
const int indentX = jmin (edgeIndent, proportionOfWidth (0.3f)); | |||||
const int indentY = jmin (edgeIndent, proportionOfHeight (0.3f)); | |||||
imageSpace.setBounds (indentX, indentY, | |||||
getWidth() - indentX * 2, | |||||
getHeight() - indentY * 2 - textH); | |||||
} | |||||
currentImage->setTransformToFit (imageSpace.toFloat(), RectanglePlacement::centred); | |||||
currentImage->setTransformToFit (imageSpace.toFloat(), RectanglePlacement::centred); | |||||
} | |||||
} | } | ||||
} | } | ||||
@@ -202,7 +202,6 @@ LookAndFeel::LookAndFeel() | |||||
ScrollBar::backgroundColourId, 0x00000000, | ScrollBar::backgroundColourId, 0x00000000, | ||||
ScrollBar::thumbColourId, 0xffffffff, | ScrollBar::thumbColourId, 0xffffffff, | ||||
ScrollBar::trackColourId, 0xffffffff, | |||||
TreeView::linesColourId, 0x4c000000, | TreeView::linesColourId, 0x4c000000, | ||||
TreeView::backgroundColourId, 0x00000000, | TreeView::backgroundColourId, 0x00000000, | ||||
@@ -870,9 +869,20 @@ void LookAndFeel::drawScrollbar (Graphics& g, | |||||
} | } | ||||
const Colour thumbColour (scrollbar.findColour (ScrollBar::thumbColourId)); | const Colour thumbColour (scrollbar.findColour (ScrollBar::thumbColourId)); | ||||
Colour trackColour1, trackColour2; | |||||
g.setGradientFill (ColourGradient (thumbColour.overlaidWith (Colour (0x44000000)), gx1, gy1, | |||||
thumbColour.overlaidWith (Colour (0x19000000)), gx2, gy2, false)); | |||||
if (scrollbar.isColourSpecified (ScrollBar::trackColourId)) | |||||
{ | |||||
trackColour1 = trackColour2 = scrollbar.findColour (ScrollBar::trackColourId); | |||||
} | |||||
else | |||||
{ | |||||
trackColour1 = thumbColour.overlaidWith (Colour (0x44000000)); | |||||
trackColour2 = thumbColour.overlaidWith (Colour (0x19000000)); | |||||
} | |||||
g.setGradientFill (ColourGradient (trackColour1, gx1, gy1, | |||||
trackColour2, gx2, gy2, false)); | |||||
g.fillPath (slotPath); | g.fillPath (slotPath); | ||||
if (isScrollbarVertical) | if (isScrollbarVertical) | ||||
@@ -38,45 +38,30 @@ BEGIN_JUCE_NAMESPACE | |||||
//============================================================================== | //============================================================================== | ||||
class ShadowWindow : public Component | class ShadowWindow : public Component | ||||
{ | { | ||||
Component* owner; | |||||
Image shadowImageSections [12]; | |||||
const int type; // 0 = left, 1 = right, 2 = top, 3 = bottom. left + right are full-height | |||||
public: | public: | ||||
ShadowWindow (Component* const owner_, | |||||
const int type_, | |||||
const Image shadowImageSections_ [12]) | |||||
: owner (owner_), | |||||
ShadowWindow (Component& owner, const int type_, const Image shadowImageSections [12]) | |||||
: topLeft (shadowImageSections [type_ * 3]), | |||||
bottomRight (shadowImageSections [type_ * 3 + 1]), | |||||
filler (shadowImageSections [type_ * 3 + 2]), | |||||
type (type_) | type (type_) | ||||
{ | { | ||||
for (int i = 0; i < numElementsInArray (shadowImageSections); ++i) | |||||
shadowImageSections [i] = shadowImageSections_ [i]; | |||||
setInterceptsMouseClicks (false, false); | setInterceptsMouseClicks (false, false); | ||||
if (owner_->isOnDesktop()) | |||||
if (owner.isOnDesktop()) | |||||
{ | { | ||||
setSize (1, 1); // to keep the OS happy by not having zero-size windows | setSize (1, 1); // to keep the OS happy by not having zero-size windows | ||||
addToDesktop (ComponentPeer::windowIgnoresMouseClicks | addToDesktop (ComponentPeer::windowIgnoresMouseClicks | ||||
| ComponentPeer::windowIsTemporary | | ComponentPeer::windowIsTemporary | ||||
| ComponentPeer::windowIgnoresKeyPresses); | | ComponentPeer::windowIgnoresKeyPresses); | ||||
} | } | ||||
else if (owner_->getParentComponent() != 0) | |||||
else if (owner.getParentComponent() != 0) | |||||
{ | { | ||||
owner_->getParentComponent()->addChildComponent (this); | |||||
owner.getParentComponent()->addChildComponent (this); | |||||
} | } | ||||
} | } | ||||
~ShadowWindow() | |||||
{ | |||||
} | |||||
void paint (Graphics& g) | void paint (Graphics& g) | ||||
{ | { | ||||
const Image& topLeft = shadowImageSections [type * 3]; | |||||
const Image& bottomRight = shadowImageSections [type * 3 + 1]; | |||||
const Image& filler = shadowImageSections [type * 3 + 2]; | |||||
g.setOpacity (1.0f); | g.setOpacity (1.0f); | ||||
if (type < 2) | if (type < 2) | ||||
@@ -117,6 +102,9 @@ public: | |||||
} | } | ||||
private: | private: | ||||
const Image topLeft, bottomRight, filler; | |||||
const int type; // 0 = left, 1 = right, 2 = top, 3 = bottom. left + right are full-height | |||||
JUCE_DECLARE_NON_COPYABLE (ShadowWindow); | JUCE_DECLARE_NON_COPYABLE (ShadowWindow); | ||||
}; | }; | ||||
@@ -127,13 +115,10 @@ DropShadower::DropShadower (const float alpha_, | |||||
const int yOffset_, | const int yOffset_, | ||||
const float blurRadius_) | const float blurRadius_) | ||||
: owner (0), | : owner (0), | ||||
numShadows (0), | |||||
shadowEdge (jmax (xOffset_, yOffset_) + (int) blurRadius_), | |||||
xOffset (xOffset_), | xOffset (xOffset_), | ||||
yOffset (yOffset_), | yOffset (yOffset_), | ||||
alpha (alpha_), | alpha (alpha_), | ||||
blurRadius (blurRadius_), | blurRadius (blurRadius_), | ||||
inDestructor (false), | |||||
reentrant (false) | reentrant (false) | ||||
{ | { | ||||
} | } | ||||
@@ -143,21 +128,8 @@ DropShadower::~DropShadower() | |||||
if (owner != 0) | if (owner != 0) | ||||
owner->removeComponentListener (this); | owner->removeComponentListener (this); | ||||
inDestructor = true; | |||||
deleteShadowWindows(); | |||||
} | |||||
void DropShadower::deleteShadowWindows() | |||||
{ | |||||
if (numShadows > 0) | |||||
{ | |||||
int i; | |||||
for (i = numShadows; --i >= 0;) | |||||
delete shadowWindows[i]; | |||||
numShadows = 0; | |||||
} | |||||
reentrant = true; | |||||
shadowWindows.clear(); | |||||
} | } | ||||
void DropShadower::setOwner (Component* componentToFollow) | void DropShadower::setOwner (Component* componentToFollow) | ||||
@@ -191,13 +163,9 @@ void DropShadower::componentBroughtToFront (Component&) | |||||
bringShadowWindowsToFront(); | bringShadowWindowsToFront(); | ||||
} | } | ||||
void DropShadower::componentChildrenChanged (Component&) | |||||
{ | |||||
} | |||||
void DropShadower::componentParentHierarchyChanged (Component&) | void DropShadower::componentParentHierarchyChanged (Component&) | ||||
{ | { | ||||
deleteShadowWindows(); | |||||
shadowWindows.clear(); | |||||
updateShadows(); | updateShadows(); | ||||
} | } | ||||
@@ -208,23 +176,23 @@ void DropShadower::componentVisibilityChanged (Component&) | |||||
void DropShadower::updateShadows() | void DropShadower::updateShadows() | ||||
{ | { | ||||
if (reentrant || inDestructor || (owner == 0)) | |||||
if (reentrant || owner == 0) | |||||
return; | return; | ||||
reentrant = true; | reentrant = true; | ||||
ComponentPeer* const nw = owner->getPeer(); | |||||
const bool isOwnerVisible = owner->isVisible() | |||||
&& (nw == 0 || ! nw->isMinimised()); | |||||
ComponentPeer* const peer = owner->getPeer(); | |||||
const bool isOwnerVisible = owner->isVisible() && (peer == 0 || ! peer->isMinimised()); | |||||
const bool createShadowWindows = numShadows == 0 | |||||
const bool createShadowWindows = shadowWindows.size() == 0 | |||||
&& owner->getWidth() > 0 | && owner->getWidth() > 0 | ||||
&& owner->getHeight() > 0 | && owner->getHeight() > 0 | ||||
&& isOwnerVisible | && isOwnerVisible | ||||
&& (Desktop::canUseSemiTransparentWindows() | && (Desktop::canUseSemiTransparentWindows() | ||||
|| owner->getParentComponent() != 0); | || owner->getParentComponent() != 0); | ||||
const int shadowEdge = jmax (xOffset, yOffset) + (int) blurRadius; | |||||
if (createShadowWindows) | if (createShadowWindows) | ||||
{ | { | ||||
// keep a cached version of the image to save doing the gaussian too often | // keep a cached version of the image to save doing the gaussian too often | ||||
@@ -274,18 +242,15 @@ void DropShadower::updateShadows() | |||||
setShadowImage (bigIm, 11, shadowEdge, shadowEdge, shadowEdge2, ih - shadowEdge); | setShadowImage (bigIm, 11, shadowEdge, shadowEdge, shadowEdge2, ih - shadowEdge); | ||||
for (int i = 0; i < 4; ++i) | for (int i = 0; i < 4; ++i) | ||||
{ | |||||
shadowWindows[numShadows] = new ShadowWindow (owner, i, shadowImageSections); | |||||
++numShadows; | |||||
} | |||||
shadowWindows.add (new ShadowWindow (*owner, i, shadowImageSections)); | |||||
} | } | ||||
if (numShadows > 0) | |||||
if (shadowWindows.size() >= 4) | |||||
{ | { | ||||
for (int i = numShadows; --i >= 0;) | |||||
for (int i = shadowWindows.size(); --i >= 0;) | |||||
{ | { | ||||
shadowWindows[i]->setAlwaysOnTop (owner->isAlwaysOnTop()); | |||||
shadowWindows[i]->setVisible (isOwnerVisible); | |||||
shadowWindows.getUnchecked(i)->setAlwaysOnTop (owner->isAlwaysOnTop()); | |||||
shadowWindows.getUnchecked(i)->setVisible (isOwnerVisible); | |||||
} | } | ||||
const int x = owner->getX(); | const int x = owner->getX(); | ||||
@@ -293,25 +258,10 @@ void DropShadower::updateShadows() | |||||
const int w = owner->getWidth(); | const int w = owner->getWidth(); | ||||
const int h = owner->getHeight() + shadowEdge + shadowEdge; | const int h = owner->getHeight() + shadowEdge + shadowEdge; | ||||
shadowWindows[0]->setBounds (x - shadowEdge, | |||||
y, | |||||
shadowEdge, | |||||
h); | |||||
shadowWindows[1]->setBounds (x + w, | |||||
y, | |||||
shadowEdge, | |||||
h); | |||||
shadowWindows[2]->setBounds (x, | |||||
y, | |||||
w, | |||||
shadowEdge); | |||||
shadowWindows[3]->setBounds (x, | |||||
owner->getBottom(), | |||||
w, | |||||
shadowEdge); | |||||
shadowWindows.getUnchecked(0)->setBounds (x - shadowEdge, y, shadowEdge, h); | |||||
shadowWindows.getUnchecked(1)->setBounds (x + w, y, shadowEdge, h); | |||||
shadowWindows.getUnchecked(2)->setBounds (x, y, w, shadowEdge); | |||||
shadowWindows.getUnchecked(3)->setBounds (x, owner->getBottom(), w, shadowEdge); | |||||
} | } | ||||
reentrant = false; | reentrant = false; | ||||
@@ -331,14 +281,14 @@ void DropShadower::setShadowImage (const Image& src, const int num, const int w, | |||||
void DropShadower::bringShadowWindowsToFront() | void DropShadower::bringShadowWindowsToFront() | ||||
{ | { | ||||
if (! (inDestructor || reentrant)) | |||||
if (! reentrant) | |||||
{ | { | ||||
updateShadows(); | updateShadows(); | ||||
reentrant = true; | reentrant = true; | ||||
for (int i = numShadows; --i >= 0;) | |||||
shadowWindows[i]->toBehind (owner); | |||||
for (int i = shadowWindows.size(); --i >= 0;) | |||||
shadowWindows.getUnchecked(i)->toBehind (owner); | |||||
reentrant = false; | reentrant = false; | ||||
} | } | ||||
@@ -71,8 +71,6 @@ public: | |||||
/** @internal */ | /** @internal */ | ||||
void componentBroughtToFront (Component& component); | void componentBroughtToFront (Component& component); | ||||
/** @internal */ | /** @internal */ | ||||
void componentChildrenChanged (Component& component); | |||||
/** @internal */ | |||||
void componentParentHierarchyChanged (Component& component); | void componentParentHierarchyChanged (Component& component); | ||||
/** @internal */ | /** @internal */ | ||||
void componentVisibilityChanged (Component& component); | void componentVisibilityChanged (Component& component); | ||||
@@ -81,17 +79,15 @@ public: | |||||
private: | private: | ||||
//============================================================================== | //============================================================================== | ||||
Component* owner; | Component* owner; | ||||
int numShadows; | |||||
Component* shadowWindows[4]; | |||||
OwnedArray<Component> shadowWindows; | |||||
Image shadowImageSections[12]; | Image shadowImageSections[12]; | ||||
const int shadowEdge, xOffset, yOffset; | |||||
const int xOffset, yOffset; | |||||
const float alpha, blurRadius; | const float alpha, blurRadius; | ||||
bool inDestructor, reentrant; | |||||
bool reentrant; | |||||
void updateShadows(); | void updateShadows(); | ||||
void setShadowImage (const Image& src, int num, int w, int h, int sx, int sy); | void setShadowImage (const Image& src, int num, int w, int h, int sx, int sy); | ||||
void bringShadowWindowsToFront(); | void bringShadowWindowsToFront(); | ||||
void deleteShadowWindows(); | |||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DropShadower); | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DropShadower); | ||||
}; | }; | ||||
@@ -52,6 +52,7 @@ void juce_CheckForDanglingStreams() | |||||
//============================================================================== | //============================================================================== | ||||
OutputStream::OutputStream() | OutputStream::OutputStream() | ||||
: newLineString (NewLine::getDefault()) | |||||
{ | { | ||||
#if JUCE_DEBUG | #if JUCE_DEBUG | ||||
activeStreams.add (this); | activeStreams.add (this); | ||||
@@ -250,6 +251,12 @@ int OutputStream::writeFromInputStream (InputStream& source, int64 numBytesToWri | |||||
return numWritten; | return numWritten; | ||||
} | } | ||||
//============================================================================== | |||||
void OutputStream::setNewLineString (const String& newLineString_) | |||||
{ | |||||
newLineString = newLineString_; | |||||
} | |||||
//============================================================================== | //============================================================================== | ||||
OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const int number) | OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const int number) | ||||
{ | { | ||||
@@ -289,5 +296,10 @@ OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const File& fileTo | |||||
return stream; | return stream; | ||||
} | } | ||||
OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const NewLine&) | |||||
{ | |||||
return stream << stream.getNewLineString(); | |||||
} | |||||
END_JUCE_NAMESPACE | END_JUCE_NAMESPACE |
@@ -201,8 +201,20 @@ public: | |||||
*/ | */ | ||||
virtual int writeFromInputStream (InputStream& source, int64 maxNumBytesToWrite); | virtual int writeFromInputStream (InputStream& source, int64 maxNumBytesToWrite); | ||||
//============================================================================== | |||||
/** Sets the string that will be written to the stream when the writeNewLine() | |||||
method is called. | |||||
By default this will be set the the value of NewLine::getDefault(). | |||||
*/ | |||||
void setNewLineString (const String& newLineString); | |||||
/** Returns the current new-line string that was set by setNewLineString(). */ | |||||
const String& getNewLineString() const throw() { return newLineString; } | |||||
private: | private: | ||||
//============================================================================== | //============================================================================== | ||||
String newLineString; | |||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OutputStream); | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OutputStream); | ||||
}; | }; | ||||
@@ -225,5 +237,14 @@ OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const MemoryBlock& | |||||
/** Writes the contents of a file to a stream. */ | /** Writes the contents of a file to a stream. */ | ||||
OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const File& fileToRead); | OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const File& fileToRead); | ||||
/** Writes a new-line to a stream. | |||||
You can use the predefined symbol 'newLine' to invoke this, e.g. | |||||
@code | |||||
myOutputStream << "Hello World" << newLine << newLine; | |||||
@endcode | |||||
@see OutputStream::setNewLineString | |||||
*/ | |||||
OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const NewLine&); | |||||
#endif // __JUCE_OUTPUTSTREAM_JUCEHEADER__ | #endif // __JUCE_OUTPUTSTREAM_JUCEHEADER__ |
@@ -46,6 +46,8 @@ BEGIN_JUCE_NAMESPACE | |||||
#error "JUCE_STRINGS_ARE_UNICODE is deprecated! All strings are now unicode by default." | #error "JUCE_STRINGS_ARE_UNICODE is deprecated! All strings are now unicode by default." | ||||
#endif | #endif | ||||
NewLine newLine; | |||||
//============================================================================== | //============================================================================== | ||||
class StringHolder | class StringHolder | ||||
{ | { | ||||
@@ -779,6 +781,11 @@ JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const Str | |||||
return stream; | return stream; | ||||
} | } | ||||
JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, const NewLine&) | |||||
{ | |||||
return string1 += NewLine::getDefault(); | |||||
} | |||||
//============================================================================== | //============================================================================== | ||||
int String::indexOfChar (const juce_wchar character) const throw() | int String::indexOfChar (const juce_wchar character) const throw() | ||||
{ | { | ||||
@@ -2167,7 +2174,6 @@ void String::copyToUnicode (juce_wchar* const destBuffer, const int maxCharsToCo | |||||
StringHolder::copyChars (destBuffer, text, jmin (maxCharsToCopy, length())); | StringHolder::copyChars (destBuffer, text, jmin (maxCharsToCopy, length())); | ||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||
String::Concatenator::Concatenator (String& stringToAppendTo) | String::Concatenator::Concatenator (String& stringToAppendTo) | ||||
: result (stringToAppendTo), | : result (stringToAppendTo), | ||||
@@ -2191,6 +2197,9 @@ void String::Concatenator::append (const String& s) | |||||
} | } | ||||
} | } | ||||
//============================================================================== | |||||
//============================================================================== | |||||
#if JUCE_UNIT_TESTS | #if JUCE_UNIT_TESTS | ||||
#include "../utilities/juce_UnitTest.h" | #include "../utilities/juce_UnitTest.h" | ||||
@@ -1145,4 +1145,47 @@ JUCE_API std::basic_ostream <charT, traits>& JUCE_CALLTYPE operator<< (std::basi | |||||
JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const String& text); | JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const String& text); | ||||
//============================================================================== | |||||
/** This class is used for represent a new-line character sequence. | |||||
To write a new-line to a stream, you can use the predefined 'newLine' variable, e.g. | |||||
@code | |||||
myOutputStream << "Hello World" << newLine << newLine; | |||||
@endcode | |||||
The exact character sequence that will be used for the new-line can be set and | |||||
retrieved with OutputStream::setNewLineString() and OutputStream::getNewLineString(). | |||||
*/ | |||||
class NewLine | |||||
{ | |||||
public: | |||||
/** Returns the default new-line sequence that the library uses. | |||||
@see OutputStream::setNewLineString() | |||||
*/ | |||||
static const char* getDefault() throw() { return "\r\n"; } | |||||
/** Returns the default new-line sequence that the library uses. | |||||
@see getDefault() | |||||
*/ | |||||
operator const String() const { return getDefault(); } | |||||
}; | |||||
/** An object representing a new-line, which can be written to a string or stream. | |||||
To write a new-line to a stream, you can use the predefined 'newLine' variable like this: | |||||
@code | |||||
myOutputStream << "Hello World" << newLine << newLine; | |||||
@endcode | |||||
*/ | |||||
extern NewLine newLine; | |||||
/** Writes a new-line sequence to a string. | |||||
You can use the predefined object 'newLine' to invoke this, e.g. | |||||
@code | |||||
myString << "Hello World" << newLine << newLine; | |||||
@endcode | |||||
*/ | |||||
JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, const NewLine&); | |||||
#endif // __JUCE_STRING_JUCEHEADER__ | #endif // __JUCE_STRING_JUCEHEADER__ |
@@ -261,11 +261,6 @@ namespace XmlOutputFunctions | |||||
out.write (blanks, numSpaces); | out.write (blanks, numSpaces); | ||||
} | } | ||||
} | } | ||||
void writeNewLine (OutputStream& out) | |||||
{ | |||||
out.write ("\r\n", 2); | |||||
} | |||||
} | } | ||||
void XmlElement::writeElementAsText (OutputStream& outputStream, | void XmlElement::writeElementAsText (OutputStream& outputStream, | ||||
@@ -288,7 +283,7 @@ void XmlElement::writeElementAsText (OutputStream& outputStream, | |||||
{ | { | ||||
if (lineLen > lineWrapLength && indentationLevel >= 0) | if (lineLen > lineWrapLength && indentationLevel >= 0) | ||||
{ | { | ||||
writeNewLine (outputStream); | |||||
outputStream << newLine; | |||||
writeSpaces (outputStream, attIndent); | writeSpaces (outputStream, attIndent); | ||||
lineLen = 0; | lineLen = 0; | ||||
} | } | ||||
@@ -320,7 +315,7 @@ void XmlElement::writeElementAsText (OutputStream& outputStream, | |||||
else | else | ||||
{ | { | ||||
if (indentationLevel >= 0 && ! lastWasTextNode) | if (indentationLevel >= 0 && ! lastWasTextNode) | ||||
writeNewLine (outputStream); | |||||
outputStream << newLine; | |||||
child->writeElementAsText (outputStream, | child->writeElementAsText (outputStream, | ||||
lastWasTextNode ? 0 : (indentationLevel + (indentationLevel >= 0 ? 2 : 0)), lineWrapLength); | lastWasTextNode ? 0 : (indentationLevel + (indentationLevel >= 0 ? 2 : 0)), lineWrapLength); | ||||
@@ -332,7 +327,7 @@ void XmlElement::writeElementAsText (OutputStream& outputStream, | |||||
if (indentationLevel >= 0 && ! lastWasTextNode) | if (indentationLevel >= 0 && ! lastWasTextNode) | ||||
{ | { | ||||
writeNewLine (outputStream); | |||||
outputStream << newLine; | |||||
writeSpaces (outputStream, indentationLevel); | writeSpaces (outputStream, indentationLevel); | ||||
} | } | ||||
@@ -377,14 +372,9 @@ void XmlElement::writeToStream (OutputStream& output, | |||||
output << "<?xml version=\"1.0\" encoding=\"" << encodingType << "\"?>"; | output << "<?xml version=\"1.0\" encoding=\"" << encodingType << "\"?>"; | ||||
if (allOnOneLine) | if (allOnOneLine) | ||||
{ | |||||
output.writeByte (' '); | output.writeByte (' '); | ||||
} | |||||
else | else | ||||
{ | |||||
writeNewLine (output); | |||||
writeNewLine (output); | |||||
} | |||||
output << newLine << newLine; | |||||
} | } | ||||
if (dtdToUse.isNotEmpty()) | if (dtdToUse.isNotEmpty()) | ||||
@@ -394,13 +384,13 @@ void XmlElement::writeToStream (OutputStream& output, | |||||
if (allOnOneLine) | if (allOnOneLine) | ||||
output.writeByte (' '); | output.writeByte (' '); | ||||
else | else | ||||
writeNewLine (output); | |||||
output << newLine; | |||||
} | } | ||||
writeElementAsText (output, allOnOneLine ? -1 : 0, lineWrapLength); | writeElementAsText (output, allOnOneLine ? -1 : 0, lineWrapLength); | ||||
if (! allOnOneLine) | if (! allOnOneLine) | ||||
writeNewLine (output); | |||||
output << newLine; | |||||
} | } | ||||
bool XmlElement::writeToFile (const File& file, | bool XmlElement::writeToFile (const File& file, | ||||