diff --git a/extras/Jucer (experimental)/Source/Application/jucer_CommonHeaders.h b/extras/Jucer (experimental)/Source/Application/jucer_CommonHeaders.h index 2cbed2c226..e2a1f94fd3 100644 --- a/extras/Jucer (experimental)/Source/Application/jucer_CommonHeaders.h +++ b/extras/Jucer (experimental)/Source/Application/jucer_CommonHeaders.h @@ -40,8 +40,6 @@ extern ApplicationCommandManager* commandManager; //============================================================================== -static const char* const newLine = "\r\n"; - const char* const projectItemDragType = "Project Items"; const char* const drawableItemDragType = "Drawable Items"; const char* const componentItemDragType = "Components"; diff --git a/extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_MSVC.h b/extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_MSVC.h index 3212a66a5f..15902c7f09 100644 --- a/extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_MSVC.h +++ b/extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_MSVC.h @@ -523,7 +523,7 @@ public: protected: 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 getSLNFile() const { return getProjectFile (".sln"); } @@ -847,7 +847,7 @@ public: protected: 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); }; diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index a4de57b159..5f3c9cf3ad 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -1227,10 +1227,10 @@ FileLogger::FileLogger (const File& logFile_, } 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); } @@ -1246,7 +1246,7 @@ void FileLogger::logMessage (const String& message) const ScopedLock sl (logLock); FileOutputStream out (logFile, 256); - out << message << "\r\n"; + out << message << newLine; } void FileLogger::trimFileSize (int maxFileSizeBytes) const @@ -6745,6 +6745,7 @@ void juce_CheckForDanglingStreams() #endif OutputStream::OutputStream() + : newLineString (NewLine::getDefault()) { #if JUCE_DEBUG activeStreams.add (this); @@ -6942,6 +6943,11 @@ int OutputStream::writeFromInputStream (InputStream& source, int64 numBytesToWri return numWritten; } +void OutputStream::setNewLineString (const String& newLineString_) +{ + newLineString = newLineString_; +} + OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const int number) { return stream << String (number); @@ -6980,6 +6986,11 @@ OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const File& fileTo return stream; } +OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const NewLine&) +{ + return stream << stream.getNewLineString(); +} + END_JUCE_NAMESPACE /*** End of inlined file: juce_OutputStream.cpp ***/ @@ -10175,7 +10186,7 @@ PerformanceCounter::PerformanceCounter (const String& name_, String s ("**** Counter for \""); s << name_ << "\" started at: " << Time::getCurrentTime().toString (true, true) - << "\r\n"; + << newLine; outputFile.appendText (s, false, false); } @@ -10219,7 +10230,7 @@ void PerformanceCounter::printStatistics() Logger::outputDebugString (s); - s << "\r\n"; + s << newLine; if (outputFile != File::nonexistent) 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." #endif +NewLine newLine; + class StringHolder { public: @@ -12376,6 +12389,11 @@ JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const Str 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() { const juce_wchar* t = text; @@ -15819,11 +15837,6 @@ namespace XmlOutputFunctions out.write (blanks, numSpaces); } } - - void writeNewLine (OutputStream& out) - { - out.write ("\r\n", 2); - } } void XmlElement::writeElementAsText (OutputStream& outputStream, @@ -15846,7 +15859,7 @@ void XmlElement::writeElementAsText (OutputStream& outputStream, { if (lineLen > lineWrapLength && indentationLevel >= 0) { - writeNewLine (outputStream); + outputStream << newLine; writeSpaces (outputStream, attIndent); lineLen = 0; } @@ -15878,7 +15891,7 @@ void XmlElement::writeElementAsText (OutputStream& outputStream, else { if (indentationLevel >= 0 && ! lastWasTextNode) - writeNewLine (outputStream); + outputStream << newLine; child->writeElementAsText (outputStream, lastWasTextNode ? 0 : (indentationLevel + (indentationLevel >= 0 ? 2 : 0)), lineWrapLength); @@ -15890,7 +15903,7 @@ void XmlElement::writeElementAsText (OutputStream& outputStream, if (indentationLevel >= 0 && ! lastWasTextNode) { - writeNewLine (outputStream); + outputStream << newLine; writeSpaces (outputStream, indentationLevel); } @@ -15935,14 +15948,9 @@ void XmlElement::writeToStream (OutputStream& output, output << ""; if (allOnOneLine) - { output.writeByte (' '); - } else - { - writeNewLine (output); - writeNewLine (output); - } + output << newLine << newLine; } if (dtdToUse.isNotEmpty()) @@ -15952,13 +15960,13 @@ void XmlElement::writeToStream (OutputStream& output, if (allOnOneLine) output.writeByte (' '); else - writeNewLine (output); + output << newLine; } writeElementAsText (output, allOnOneLine ? -1 : 0, lineWrapLength); if (! allOnOneLine) - writeNewLine (output); + output << newLine; } bool XmlElement::writeToFile (const File& file, @@ -44121,33 +44129,34 @@ void DrawableButton::resized() { Button::resized(); - if (style == ImageRaw) - { - currentImage->setOriginWithOriginalSize (Point()); - } - else if (currentImage != 0) + if (currentImage != 0) { - Rectangle imageSpace; - - if (style == ImageOnButtonBackground) + if (style == ImageRaw) { - imageSpace = getLocalBounds().reduced (getWidth() / 4, getHeight() / 4); + currentImage->setOriginWithOriginalSize (Point()); } else { - const int textH = (style == ImageAboveTextLabel) - ? jmin (16, proportionOfHeight (0.25f)) - : 0; + Rectangle 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::thumbColourId, 0xffffffff, - ScrollBar::trackColourId, 0xffffffff, TreeView::linesColourId, 0x4c000000, TreeView::backgroundColourId, 0x00000000, @@ -65583,9 +65591,20 @@ void LookAndFeel::drawScrollbar (Graphics& g, } 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); if (isScrollbarVertical) @@ -74513,45 +74532,30 @@ BEGIN_JUCE_NAMESPACE 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: - 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_) { - for (int i = 0; i < numElementsInArray (shadowImageSections); ++i) - shadowImageSections [i] = shadowImageSections_ [i]; - setInterceptsMouseClicks (false, false); - if (owner_->isOnDesktop()) + if (owner.isOnDesktop()) { setSize (1, 1); // to keep the OS happy by not having zero-size windows addToDesktop (ComponentPeer::windowIgnoresMouseClicks | ComponentPeer::windowIsTemporary | 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) { - const Image& topLeft = shadowImageSections [type * 3]; - const Image& bottomRight = shadowImageSections [type * 3 + 1]; - const Image& filler = shadowImageSections [type * 3 + 2]; - g.setOpacity (1.0f); if (type < 2) @@ -74592,6 +74596,9 @@ public: } 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); }; @@ -74600,13 +74607,10 @@ DropShadower::DropShadower (const float alpha_, const int yOffset_, const float blurRadius_) : owner (0), - numShadows (0), - shadowEdge (jmax (xOffset_, yOffset_) + (int) blurRadius_), xOffset (xOffset_), yOffset (yOffset_), alpha (alpha_), blurRadius (blurRadius_), - inDestructor (false), reentrant (false) { } @@ -74616,21 +74620,8 @@ DropShadower::~DropShadower() if (owner != 0) 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) @@ -74664,13 +74655,9 @@ void DropShadower::componentBroughtToFront (Component&) bringShadowWindowsToFront(); } -void DropShadower::componentChildrenChanged (Component&) -{ -} - void DropShadower::componentParentHierarchyChanged (Component&) { - deleteShadowWindows(); + shadowWindows.clear(); updateShadows(); } @@ -74681,23 +74668,23 @@ void DropShadower::componentVisibilityChanged (Component&) void DropShadower::updateShadows() { - if (reentrant || inDestructor || (owner == 0)) + if (reentrant || owner == 0) return; 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->getHeight() > 0 && isOwnerVisible && (Desktop::canUseSemiTransparentWindows() || owner->getParentComponent() != 0); + const int shadowEdge = jmax (xOffset, yOffset) + (int) blurRadius; + if (createShadowWindows) { // 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); 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(); @@ -74766,25 +74750,10 @@ void DropShadower::updateShadows() const int w = owner->getWidth(); 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; @@ -74804,14 +74773,14 @@ void DropShadower::setShadowImage (const Image& src, const int num, const int w, void DropShadower::bringShadowWindowsToFront() { - if (! (inDestructor || reentrant)) + if (! reentrant) { updateShadows(); 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; } diff --git a/juce_amalgamated.h b/juce_amalgamated.h index b84ffc2d83..361671fdd8 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -2804,6 +2804,47 @@ JUCE_API std::basic_ostream & JUCE_CALLTYPE operator<< (std::basi /** Writes a string to an OutputStream as UTF8. */ 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__ /*** End of inlined file: juce_String.h ***/ @@ -6235,8 +6276,19 @@ public: */ 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: + String newLineString; + 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. */ 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__ /*** End of inlined file: juce_OutputStream.h ***/ @@ -50898,8 +50959,6 @@ public: /** @internal */ void componentBroughtToFront (Component& component); /** @internal */ - void componentChildrenChanged (Component& component); - /** @internal */ void componentParentHierarchyChanged (Component& component); /** @internal */ void componentVisibilityChanged (Component& component); @@ -50907,17 +50966,15 @@ public: private: Component* owner; - int numShadows; - Component* shadowWindows[4]; + OwnedArray shadowWindows; Image shadowImageSections[12]; - const int shadowEdge, xOffset, yOffset; + const int xOffset, yOffset; const float alpha, blurRadius; - bool inDestructor, reentrant; + bool reentrant; void updateShadows(); void setShadowImage (const Image& src, int num, int w, int h, int sx, int sy); void bringShadowWindowsToFront(); - void deleteShadowWindows(); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DropShadower); }; diff --git a/src/core/juce_FileLogger.cpp b/src/core/juce_FileLogger.cpp index d6dfd64eca..19cea7834b 100644 --- a/src/core/juce_FileLogger.cpp +++ b/src/core/juce_FileLogger.cpp @@ -51,10 +51,10 @@ FileLogger::FileLogger (const File& logFile_, } 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); } @@ -71,7 +71,7 @@ void FileLogger::logMessage (const String& message) const ScopedLock sl (logLock); FileOutputStream out (logFile, 256); - out << message << "\r\n"; + out << message << newLine; } diff --git a/src/core/juce_PerformanceCounter.cpp b/src/core/juce_PerformanceCounter.cpp index 7f344becef..c197ece203 100644 --- a/src/core/juce_PerformanceCounter.cpp +++ b/src/core/juce_PerformanceCounter.cpp @@ -46,7 +46,7 @@ PerformanceCounter::PerformanceCounter (const String& name_, String s ("**** Counter for \""); s << name_ << "\" started at: " << Time::getCurrentTime().toString (true, true) - << "\r\n"; + << newLine; outputFile.appendText (s, false, false); } @@ -90,7 +90,7 @@ void PerformanceCounter::printStatistics() Logger::outputDebugString (s); - s << "\r\n"; + s << newLine; if (outputFile != File::nonexistent) outputFile.appendText (s, false, false); diff --git a/src/gui/components/buttons/juce_DrawableButton.cpp b/src/gui/components/buttons/juce_DrawableButton.cpp index 6ef746bd0e..ae7bec5fcd 100644 --- a/src/gui/components/buttons/juce_DrawableButton.cpp +++ b/src/gui/components/buttons/juce_DrawableButton.cpp @@ -119,33 +119,34 @@ void DrawableButton::resized() { Button::resized(); - if (style == ImageRaw) - { - currentImage->setOriginWithOriginalSize (Point()); - } - else if (currentImage != 0) + if (currentImage != 0) { - Rectangle imageSpace; - - if (style == ImageOnButtonBackground) + if (style == ImageRaw) { - imageSpace = getLocalBounds().reduced (getWidth() / 4, getHeight() / 4); + currentImage->setOriginWithOriginalSize (Point()); } else { - const int textH = (style == ImageAboveTextLabel) - ? jmin (16, proportionOfHeight (0.25f)) - : 0; + Rectangle 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); + } } } diff --git a/src/gui/components/lookandfeel/juce_LookAndFeel.cpp b/src/gui/components/lookandfeel/juce_LookAndFeel.cpp index b7c65860e9..dbc9a72515 100644 --- a/src/gui/components/lookandfeel/juce_LookAndFeel.cpp +++ b/src/gui/components/lookandfeel/juce_LookAndFeel.cpp @@ -202,7 +202,6 @@ LookAndFeel::LookAndFeel() ScrollBar::backgroundColourId, 0x00000000, ScrollBar::thumbColourId, 0xffffffff, - ScrollBar::trackColourId, 0xffffffff, TreeView::linesColourId, 0x4c000000, TreeView::backgroundColourId, 0x00000000, @@ -870,9 +869,20 @@ void LookAndFeel::drawScrollbar (Graphics& g, } 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); if (isScrollbarVertical) diff --git a/src/gui/components/special/juce_DropShadower.cpp b/src/gui/components/special/juce_DropShadower.cpp index ca028b67e0..438ff25ccf 100644 --- a/src/gui/components/special/juce_DropShadower.cpp +++ b/src/gui/components/special/juce_DropShadower.cpp @@ -38,45 +38,30 @@ BEGIN_JUCE_NAMESPACE //============================================================================== 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: - 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_) { - for (int i = 0; i < numElementsInArray (shadowImageSections); ++i) - shadowImageSections [i] = shadowImageSections_ [i]; - setInterceptsMouseClicks (false, false); - if (owner_->isOnDesktop()) + if (owner.isOnDesktop()) { setSize (1, 1); // to keep the OS happy by not having zero-size windows addToDesktop (ComponentPeer::windowIgnoresMouseClicks | ComponentPeer::windowIsTemporary | 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) { - const Image& topLeft = shadowImageSections [type * 3]; - const Image& bottomRight = shadowImageSections [type * 3 + 1]; - const Image& filler = shadowImageSections [type * 3 + 2]; - g.setOpacity (1.0f); if (type < 2) @@ -117,6 +102,9 @@ public: } 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); }; @@ -127,13 +115,10 @@ DropShadower::DropShadower (const float alpha_, const int yOffset_, const float blurRadius_) : owner (0), - numShadows (0), - shadowEdge (jmax (xOffset_, yOffset_) + (int) blurRadius_), xOffset (xOffset_), yOffset (yOffset_), alpha (alpha_), blurRadius (blurRadius_), - inDestructor (false), reentrant (false) { } @@ -143,21 +128,8 @@ DropShadower::~DropShadower() if (owner != 0) 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) @@ -191,13 +163,9 @@ void DropShadower::componentBroughtToFront (Component&) bringShadowWindowsToFront(); } -void DropShadower::componentChildrenChanged (Component&) -{ -} - void DropShadower::componentParentHierarchyChanged (Component&) { - deleteShadowWindows(); + shadowWindows.clear(); updateShadows(); } @@ -208,23 +176,23 @@ void DropShadower::componentVisibilityChanged (Component&) void DropShadower::updateShadows() { - if (reentrant || inDestructor || (owner == 0)) + if (reentrant || owner == 0) return; 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->getHeight() > 0 && isOwnerVisible && (Desktop::canUseSemiTransparentWindows() || owner->getParentComponent() != 0); + const int shadowEdge = jmax (xOffset, yOffset) + (int) blurRadius; + if (createShadowWindows) { // 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); 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(); @@ -293,25 +258,10 @@ void DropShadower::updateShadows() const int w = owner->getWidth(); 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; @@ -331,14 +281,14 @@ void DropShadower::setShadowImage (const Image& src, const int num, const int w, void DropShadower::bringShadowWindowsToFront() { - if (! (inDestructor || reentrant)) + if (! reentrant) { updateShadows(); 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; } diff --git a/src/gui/components/special/juce_DropShadower.h b/src/gui/components/special/juce_DropShadower.h index 4cd691da2d..9320187ade 100644 --- a/src/gui/components/special/juce_DropShadower.h +++ b/src/gui/components/special/juce_DropShadower.h @@ -71,8 +71,6 @@ public: /** @internal */ void componentBroughtToFront (Component& component); /** @internal */ - void componentChildrenChanged (Component& component); - /** @internal */ void componentParentHierarchyChanged (Component& component); /** @internal */ void componentVisibilityChanged (Component& component); @@ -81,17 +79,15 @@ public: private: //============================================================================== Component* owner; - int numShadows; - Component* shadowWindows[4]; + OwnedArray shadowWindows; Image shadowImageSections[12]; - const int shadowEdge, xOffset, yOffset; + const int xOffset, yOffset; const float alpha, blurRadius; - bool inDestructor, reentrant; + bool reentrant; void updateShadows(); void setShadowImage (const Image& src, int num, int w, int h, int sx, int sy); void bringShadowWindowsToFront(); - void deleteShadowWindows(); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DropShadower); }; diff --git a/src/io/streams/juce_OutputStream.cpp b/src/io/streams/juce_OutputStream.cpp index 1d79f4c29b..da6ff758de 100644 --- a/src/io/streams/juce_OutputStream.cpp +++ b/src/io/streams/juce_OutputStream.cpp @@ -52,6 +52,7 @@ void juce_CheckForDanglingStreams() //============================================================================== OutputStream::OutputStream() + : newLineString (NewLine::getDefault()) { #if JUCE_DEBUG activeStreams.add (this); @@ -250,6 +251,12 @@ int OutputStream::writeFromInputStream (InputStream& source, int64 numBytesToWri return numWritten; } +//============================================================================== +void OutputStream::setNewLineString (const String& newLineString_) +{ + newLineString = newLineString_; +} + //============================================================================== OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const int number) { @@ -289,5 +296,10 @@ OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const File& fileTo return stream; } +OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const NewLine&) +{ + return stream << stream.getNewLineString(); +} + END_JUCE_NAMESPACE diff --git a/src/io/streams/juce_OutputStream.h b/src/io/streams/juce_OutputStream.h index 34c967c900..37a9b968de 100644 --- a/src/io/streams/juce_OutputStream.h +++ b/src/io/streams/juce_OutputStream.h @@ -201,8 +201,20 @@ public: */ 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: //============================================================================== + String newLineString; + 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. */ 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__ diff --git a/src/text/juce_String.cpp b/src/text/juce_String.cpp index 6bb203e78e..e9e60b3561 100644 --- a/src/text/juce_String.cpp +++ b/src/text/juce_String.cpp @@ -46,6 +46,8 @@ BEGIN_JUCE_NAMESPACE #error "JUCE_STRINGS_ARE_UNICODE is deprecated! All strings are now unicode by default." #endif +NewLine newLine; + //============================================================================== class StringHolder { @@ -779,6 +781,11 @@ JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const Str 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() { @@ -2167,7 +2174,6 @@ void String::copyToUnicode (juce_wchar* const destBuffer, const int maxCharsToCo StringHolder::copyChars (destBuffer, text, jmin (maxCharsToCopy, length())); } - //============================================================================== String::Concatenator::Concatenator (String& stringToAppendTo) : result (stringToAppendTo), @@ -2191,6 +2197,9 @@ void String::Concatenator::append (const String& s) } } + +//============================================================================== +//============================================================================== #if JUCE_UNIT_TESTS #include "../utilities/juce_UnitTest.h" diff --git a/src/text/juce_String.h b/src/text/juce_String.h index 19aff2aa5b..0b8b0fc7d3 100644 --- a/src/text/juce_String.h +++ b/src/text/juce_String.h @@ -1145,4 +1145,47 @@ JUCE_API std::basic_ostream & JUCE_CALLTYPE operator<< (std::basi 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__ diff --git a/src/text/juce_XmlElement.cpp b/src/text/juce_XmlElement.cpp index 2d4bdc3e94..6929ee322f 100644 --- a/src/text/juce_XmlElement.cpp +++ b/src/text/juce_XmlElement.cpp @@ -261,11 +261,6 @@ namespace XmlOutputFunctions out.write (blanks, numSpaces); } } - - void writeNewLine (OutputStream& out) - { - out.write ("\r\n", 2); - } } void XmlElement::writeElementAsText (OutputStream& outputStream, @@ -288,7 +283,7 @@ void XmlElement::writeElementAsText (OutputStream& outputStream, { if (lineLen > lineWrapLength && indentationLevel >= 0) { - writeNewLine (outputStream); + outputStream << newLine; writeSpaces (outputStream, attIndent); lineLen = 0; } @@ -320,7 +315,7 @@ void XmlElement::writeElementAsText (OutputStream& outputStream, else { if (indentationLevel >= 0 && ! lastWasTextNode) - writeNewLine (outputStream); + outputStream << newLine; child->writeElementAsText (outputStream, lastWasTextNode ? 0 : (indentationLevel + (indentationLevel >= 0 ? 2 : 0)), lineWrapLength); @@ -332,7 +327,7 @@ void XmlElement::writeElementAsText (OutputStream& outputStream, if (indentationLevel >= 0 && ! lastWasTextNode) { - writeNewLine (outputStream); + outputStream << newLine; writeSpaces (outputStream, indentationLevel); } @@ -377,14 +372,9 @@ void XmlElement::writeToStream (OutputStream& output, output << ""; if (allOnOneLine) - { output.writeByte (' '); - } else - { - writeNewLine (output); - writeNewLine (output); - } + output << newLine << newLine; } if (dtdToUse.isNotEmpty()) @@ -394,13 +384,13 @@ void XmlElement::writeToStream (OutputStream& output, if (allOnOneLine) output.writeByte (' '); else - writeNewLine (output); + output << newLine; } writeElementAsText (output, allOnOneLine ? -1 : 0, lineWrapLength); if (! allOnOneLine) - writeNewLine (output); + output << newLine; } bool XmlElement::writeToFile (const File& file,