| @@ -52,6 +52,8 @@ void PlatformUtilities::beep() | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| #if ! JUCE_ONLY_BUILD_CORE_LIBRARY | |||||
| bool AlertWindow::showNativeDialogBox (const String& title, | bool AlertWindow::showNativeDialogBox (const String& title, | ||||
| const String& bodyText, | const String& bodyText, | ||||
| bool isOkCancel) | bool isOkCancel) | ||||
| @@ -242,3 +244,6 @@ void juce_updateMultiMonitorInfo (Array <Rectangle>& monitorCoords, const bool c | |||||
| } | } | ||||
| #endif | #endif | ||||
| #endif | |||||
| @@ -67,6 +67,8 @@ | |||||
| #if MACOS_10_4_OR_EARLIER | #if MACOS_10_4_OR_EARLIER | ||||
| #include <GLUT/glut.h> | #include <GLUT/glut.h> | ||||
| typedef int NSInteger; | |||||
| typedef unsigned int NSUInteger; | |||||
| #endif | #endif | ||||
| #endif // __JUCE_MAC_NATIVEINCLUDES_JUCEHEADER__ | #endif // __JUCE_MAC_NATIVEINCLUDES_JUCEHEADER__ | ||||
| @@ -59,6 +59,9 @@ bool QuickTimeMovieComponent::isQuickTimeAvailable() throw() | |||||
| static QTMovie* openMovieFromStream (InputStream* movieStream, File& movieFile) | static QTMovie* openMovieFromStream (InputStream* movieStream, File& movieFile) | ||||
| { | { | ||||
| // unfortunately, QTMovie objects can only be created on the main thread.. | |||||
| jassert (MessageManager::getInstance()->isThisTheMessageThread()); | |||||
| QTMovie* movie = 0; | QTMovie* movie = 0; | ||||
| FileInputStream* const fin = dynamic_cast <FileInputStream*> (movieStream); | FileInputStream* const fin = dynamic_cast <FileInputStream*> (movieStream); | ||||
| @@ -165,6 +165,8 @@ const String PlatformUtilities::convertToPrecomposedUnicode (const String& s) | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| #if ! JUCE_ONLY_BUILD_CORE_LIBRARY | |||||
| void SystemClipboard::copyTextToClipboard (const String& text) throw() | void SystemClipboard::copyTextToClipboard (const String& text) throw() | ||||
| { | { | ||||
| [[NSPasteboard generalPasteboard] declareTypes: [NSArray arrayWithObject: NSStringPboardType] | [[NSPasteboard generalPasteboard] declareTypes: [NSArray arrayWithObject: NSStringPboardType] | ||||
| @@ -182,5 +184,6 @@ const String SystemClipboard::getTextFromClipboard() throw() | |||||
| : nsStringToJuce (text); | : nsStringToJuce (text); | ||||
| } | } | ||||
| #endif | |||||
| #endif | #endif | ||||
| @@ -224,12 +224,10 @@ bool juce_canWriteToFile (const String& fileName) throw() | |||||
| bool juce_deleteFile (const String& fileName) throw() | bool juce_deleteFile (const String& fileName) throw() | ||||
| { | { | ||||
| const char* const fileNameUTF8 = fileName.toUTF8(); | |||||
| if (juce_isDirectory (fileName)) | if (juce_isDirectory (fileName)) | ||||
| return rmdir (fileNameUTF8) == 0; | |||||
| return rmdir ((const char*) fileName.toUTF8()) == 0; | |||||
| else | else | ||||
| return remove (fileNameUTF8) == 0; | |||||
| return remove ((const char*) fileName.toUTF8()) == 0; | |||||
| } | } | ||||
| bool juce_moveFile (const String& source, const String& dest) throw() | bool juce_moveFile (const String& source, const String& dest) throw() | ||||
| @@ -256,14 +254,13 @@ void juce_createDirectory (const String& fileName) throw() | |||||
| void* juce_fileOpen (const String& fileName, bool forWriting) throw() | void* juce_fileOpen (const String& fileName, bool forWriting) throw() | ||||
| { | { | ||||
| const char* const fileNameUTF8 = fileName.toUTF8(); | |||||
| int flags = O_RDONLY; | int flags = O_RDONLY; | ||||
| if (forWriting) | if (forWriting) | ||||
| { | { | ||||
| if (juce_fileExists (fileName, false)) | if (juce_fileExists (fileName, false)) | ||||
| { | { | ||||
| const int f = open (fileNameUTF8, O_RDWR, 00644); | |||||
| const int f = open ((const char*) fileName.toUTF8(), O_RDWR, 00644); | |||||
| if (f != -1) | if (f != -1) | ||||
| lseek (f, 0, SEEK_END); | lseek (f, 0, SEEK_END); | ||||
| @@ -276,7 +273,7 @@ void* juce_fileOpen (const String& fileName, bool forWriting) throw() | |||||
| } | } | ||||
| } | } | ||||
| return (void*) open (fileNameUTF8, flags, 00644); | |||||
| return (void*) open ((const char*) fileName.toUTF8(), flags, 00644); | |||||
| } | } | ||||
| void juce_fileClose (void* handle) throw() | void juce_fileClose (void* handle) throw() | ||||
| @@ -267,7 +267,9 @@ If you also want to build an RTAS, then carry on reading... | |||||
| the "libPluginLibrary.a" item inside it. Drag this subitem down to your Target/"Link Binary With Libraries" | the "libPluginLibrary.a" item inside it. Drag this subitem down to your Target/"Link Binary With Libraries" | ||||
| build stage and drop it there to add it to the link process. | build stage and drop it there to add it to the link process. | ||||
| - In your Info.plist, change the "Bundle OS Type Code" to "TDMw", and the "Bundle Creator OS Type Code" to | - In your Info.plist, change the "Bundle OS Type Code" to "TDMw", and the "Bundle Creator OS Type Code" to | ||||
| "PTul". | |||||
| "PTul". | |||||
| - You may need to remove the "OTHER_CFLAGS = -x c++" from the RTAS settings file to stop it complaining about | |||||
| obj-C code | |||||
| You should now be able to build an RTAS! Again, just renaming the finished bundle to ".dpm" and | You should now be able to build an RTAS! Again, just renaming the finished bundle to ".dpm" and | ||||
| putting it in your RTAS folder should be do the trick. | putting it in your RTAS folder should be do the trick. | ||||
| @@ -385,7 +385,7 @@ void ComponentLayoutEditor::filesDropped (const StringArray& filenames, int x, i | |||||
| if (newOne != 0) | if (newOne != 0) | ||||
| { | { | ||||
| JucerComponentHandler::setJucerComponentFile (*layout.getDocument(), newOne, f.getFullPathName()); | |||||
| JucerComponentHandler::setJucerComponentFile (*layout.getDocument(), newOne, f.getRelativePathFrom (document.getFile().getParentDirectory())); | |||||
| layout.getSelectedSet().selectOnly (newOne); | layout.getSelectedSet().selectOnly (newOne); | ||||
| } | } | ||||
| @@ -612,6 +612,8 @@ | |||||
| #if MACOS_10_4_OR_EARLIER | #if MACOS_10_4_OR_EARLIER | ||||
| #include <GLUT/glut.h> | #include <GLUT/glut.h> | ||||
| typedef int NSInteger; | |||||
| typedef unsigned int NSUInteger; | |||||
| #endif | #endif | ||||
| #endif // __JUCE_MAC_NATIVEINCLUDES_JUCEHEADER__ | #endif // __JUCE_MAC_NATIVEINCLUDES_JUCEHEADER__ | ||||
| @@ -630,7 +632,7 @@ | |||||
| #pragma warning (disable: 4309 4305) | #pragma warning (disable: 4309 4305) | ||||
| #endif | #endif | ||||
| #if JUCE_MAC && JUCE_32BIT && JUCE_SUPPORT_CARBON | |||||
| #if JUCE_MAC && JUCE_32BIT && JUCE_SUPPORT_CARBON && ! JUCE_ONLY_BUILD_CORE_LIBRARY | |||||
| BEGIN_JUCE_NAMESPACE | BEGIN_JUCE_NAMESPACE | ||||
| /********* Start of inlined file: juce_mac_CarbonViewWrapperComponent.h *********/ | /********* Start of inlined file: juce_mac_CarbonViewWrapperComponent.h *********/ | ||||
| @@ -2778,7 +2780,7 @@ void BitArray::ensureSize (const int numVals) throw() | |||||
| } | } | ||||
| } | } | ||||
| const String BitArray::toString (const int base) const throw() | |||||
| const String BitArray::toString (const int base, const int minimumNumCharacters) const throw() | |||||
| { | { | ||||
| String s; | String s; | ||||
| BitArray v (*this); | BitArray v (*this); | ||||
| @@ -2821,8 +2823,10 @@ const String BitArray::toString (const int base) const throw() | |||||
| return String::empty; | return String::empty; | ||||
| } | } | ||||
| if (s.isEmpty()) | |||||
| return T("0"); | |||||
| const int length = s.length(); | |||||
| if (length < minimumNumCharacters) | |||||
| s = String::repeatedString (T("0"), minimumNumCharacters - length); | |||||
| return isNegative() ? T("-") + s : s; | return isNegative() ? T("-") + s : s; | ||||
| } | } | ||||
| @@ -12606,6 +12610,20 @@ void StringPairArray::setIgnoresCase (const bool shouldIgnoreCase) throw() | |||||
| ignoreCase = shouldIgnoreCase; | ignoreCase = shouldIgnoreCase; | ||||
| } | } | ||||
| const String StringPairArray::getDescription() const | |||||
| { | |||||
| String s; | |||||
| for (int i = 0; i < keys.size(); ++i) | |||||
| { | |||||
| s << keys[i] << T(" = ") << values[i]; | |||||
| if (i < keys.size()) | |||||
| s << T(", "); | |||||
| } | |||||
| return s; | |||||
| } | |||||
| void StringPairArray::minimiseStorageOverheads() throw() | void StringPairArray::minimiseStorageOverheads() throw() | ||||
| { | { | ||||
| keys.minimiseStorageOverheads(); | keys.minimiseStorageOverheads(); | ||||
| @@ -19415,8 +19433,6 @@ public: | |||||
| #ifdef WIN32 | #ifdef WIN32 | ||||
| if (InitializeQTML (0) != noErr) | if (InitializeQTML (0) != noErr) | ||||
| return; | return; | ||||
| #elif JUCE_MAC | |||||
| EnterMoviesOnThread (0); | |||||
| #endif | #endif | ||||
| if (EnterMovies() != noErr) | if (EnterMovies() != noErr) | ||||
| return; | return; | ||||
| @@ -42497,7 +42513,7 @@ void ImageButton::setImages (const bool resizeButtonNowToFitThisImage, | |||||
| Image* ImageButton::getCurrentImage() const | Image* ImageButton::getCurrentImage() const | ||||
| { | { | ||||
| if (isDown()) | |||||
| if (isDown() || getToggleState()) | |||||
| return getDownImage(); | return getDownImage(); | ||||
| if (isOver()) | if (isOver()) | ||||
| @@ -45312,7 +45328,7 @@ double Slider::getMaxValue() const throw() | |||||
| return valueMax; | return valueMax; | ||||
| } | } | ||||
| void Slider::setMinValue (double newValue, const bool sendUpdateMessage, const bool sendMessageSynchronously) | |||||
| void Slider::setMinValue (double newValue, const bool sendUpdateMessage, const bool sendMessageSynchronously, const bool allowNudgingOfOtherValues) | |||||
| { | { | ||||
| // The minimum value only applies to sliders that are in two- or three-value mode. | // The minimum value only applies to sliders that are in two- or three-value mode. | ||||
| jassert (style == TwoValueHorizontal || style == TwoValueVertical | jassert (style == TwoValueHorizontal || style == TwoValueVertical | ||||
| @@ -45321,9 +45337,19 @@ void Slider::setMinValue (double newValue, const bool sendUpdateMessage, const b | |||||
| newValue = constrainedValue (newValue); | newValue = constrainedValue (newValue); | ||||
| if (style == TwoValueHorizontal || style == TwoValueVertical) | if (style == TwoValueHorizontal || style == TwoValueVertical) | ||||
| { | |||||
| if (allowNudgingOfOtherValues && newValue > valueMax) | |||||
| setMaxValue (newValue, sendUpdateMessage, sendMessageSynchronously); | |||||
| newValue = jmin (valueMax, newValue); | newValue = jmin (valueMax, newValue); | ||||
| } | |||||
| else | else | ||||
| { | |||||
| if (allowNudgingOfOtherValues && newValue > currentValue) | |||||
| setValue (newValue, sendUpdateMessage, sendMessageSynchronously); | |||||
| newValue = jmin (currentValue, newValue); | newValue = jmin (currentValue, newValue); | ||||
| } | |||||
| if (valueMin != newValue) | if (valueMin != newValue) | ||||
| { | { | ||||
| @@ -45341,7 +45367,7 @@ void Slider::setMinValue (double newValue, const bool sendUpdateMessage, const b | |||||
| } | } | ||||
| } | } | ||||
| void Slider::setMaxValue (double newValue, const bool sendUpdateMessage, const bool sendMessageSynchronously) | |||||
| void Slider::setMaxValue (double newValue, const bool sendUpdateMessage, const bool sendMessageSynchronously, const bool allowNudgingOfOtherValues) | |||||
| { | { | ||||
| // The maximum value only applies to sliders that are in two- or three-value mode. | // The maximum value only applies to sliders that are in two- or three-value mode. | ||||
| jassert (style == TwoValueHorizontal || style == TwoValueVertical | jassert (style == TwoValueHorizontal || style == TwoValueVertical | ||||
| @@ -45350,9 +45376,19 @@ void Slider::setMaxValue (double newValue, const bool sendUpdateMessage, const b | |||||
| newValue = constrainedValue (newValue); | newValue = constrainedValue (newValue); | ||||
| if (style == TwoValueHorizontal || style == TwoValueVertical) | if (style == TwoValueHorizontal || style == TwoValueVertical) | ||||
| { | |||||
| if (allowNudgingOfOtherValues && newValue < valueMin) | |||||
| setMinValue (newValue, sendUpdateMessage, sendMessageSynchronously); | |||||
| newValue = jmax (valueMin, newValue); | newValue = jmax (valueMin, newValue); | ||||
| } | |||||
| else | else | ||||
| { | |||||
| if (allowNudgingOfOtherValues && newValue < currentValue) | |||||
| setValue (newValue, sendUpdateMessage, sendMessageSynchronously); | |||||
| newValue = jmax (currentValue, newValue); | newValue = jmax (currentValue, newValue); | ||||
| } | |||||
| if (valueMax != newValue) | if (valueMax != newValue) | ||||
| { | { | ||||
| @@ -45748,6 +45784,10 @@ void Slider::mouseDown (const MouseEvent& e) | |||||
| { | { | ||||
| mouseWasHidden = false; | mouseWasHidden = false; | ||||
| incDecDragged = false; | incDecDragged = false; | ||||
| mouseXWhenLastDragged = e.x; | |||||
| mouseYWhenLastDragged = e.y; | |||||
| mouseDragStartX = e.getMouseDownX(); | |||||
| mouseDragStartY = e.getMouseDownY(); | |||||
| if (isEnabled()) | if (isEnabled()) | ||||
| { | { | ||||
| @@ -45826,8 +45866,6 @@ void Slider::mouseDown (const MouseEvent& e) | |||||
| minMaxDiff = valueMax - valueMin; | minMaxDiff = valueMax - valueMin; | ||||
| mouseXWhenLastDragged = e.x; | |||||
| mouseYWhenLastDragged = e.y; | |||||
| lastAngle = rotaryStart + (rotaryEnd - rotaryStart) | lastAngle = rotaryStart + (rotaryEnd - rotaryStart) | ||||
| * valueToProportionOfLength (currentValue); | * valueToProportionOfLength (currentValue); | ||||
| @@ -46016,13 +46054,14 @@ void Slider::mouseDrag (const MouseEvent& e) | |||||
| && valueBox != 0 && valueBox->isEditable()) | && valueBox != 0 && valueBox->isEditable()) | ||||
| return; | return; | ||||
| if (style == IncDecButtons) | |||||
| if (style == IncDecButtons && ! incDecDragged) | |||||
| { | { | ||||
| if (! incDecDragged) | |||||
| incDecDragged = e.getDistanceFromDragStart() > 10 && ! e.mouseWasClicked(); | |||||
| if (! incDecDragged) | |||||
| if (e.getDistanceFromDragStart() < 10 || e.mouseWasClicked()) | |||||
| return; | return; | ||||
| incDecDragged = true; | |||||
| mouseDragStartX = e.x; | |||||
| mouseDragStartY = e.y; | |||||
| } | } | ||||
| if ((isVelocityBased == (userKeyOverridesVelocity ? e.mods.testFlags (ModifierKeys::ctrlModifier | ModifierKeys::commandModifier | ModifierKeys::altModifier) | if ((isVelocityBased == (userKeyOverridesVelocity ? e.mods.testFlags (ModifierKeys::ctrlModifier | ModifierKeys::commandModifier | ModifierKeys::altModifier) | ||||
| @@ -46043,8 +46082,8 @@ void Slider::mouseDrag (const MouseEvent& e) | |||||
| || style == LinearHorizontal | || style == LinearHorizontal | ||||
| || style == LinearBar | || style == LinearBar | ||||
| || (style == IncDecButtons && incDecDragDirectionIsHorizontal())) | || (style == IncDecButtons && incDecDragDirectionIsHorizontal())) | ||||
| ? e.getDistanceFromDragStartX() | |||||
| : -e.getDistanceFromDragStartY(); | |||||
| ? e.x - mouseDragStartX | |||||
| : mouseDragStartY - e.y; | |||||
| double newPos = valueToProportionOfLength (valueOnMouseDown) | double newPos = valueToProportionOfLength (valueOnMouseDown) | ||||
| + mouseDiff * (1.0 / pixelsForFullDragExtent); | + mouseDiff * (1.0 / pixelsForFullDragExtent); | ||||
| @@ -46109,10 +46148,10 @@ void Slider::mouseDrag (const MouseEvent& e) | |||||
| else if (sliderBeingDragged == 1) | else if (sliderBeingDragged == 1) | ||||
| { | { | ||||
| setMinValue (snapValue (valueWhenLastDragged, true), | setMinValue (snapValue (valueWhenLastDragged, true), | ||||
| ! sendChangeOnlyOnRelease, false); | |||||
| ! sendChangeOnlyOnRelease, false, true); | |||||
| if (e.mods.isShiftDown()) | if (e.mods.isShiftDown()) | ||||
| setMaxValue (getMinValue() + minMaxDiff, false); | |||||
| setMaxValue (getMinValue() + minMaxDiff, false, false, true); | |||||
| else | else | ||||
| minMaxDiff = valueMax - valueMin; | minMaxDiff = valueMax - valueMin; | ||||
| } | } | ||||
| @@ -46121,10 +46160,10 @@ void Slider::mouseDrag (const MouseEvent& e) | |||||
| jassert (sliderBeingDragged == 2); | jassert (sliderBeingDragged == 2); | ||||
| setMaxValue (snapValue (valueWhenLastDragged, true), | setMaxValue (snapValue (valueWhenLastDragged, true), | ||||
| ! sendChangeOnlyOnRelease, false); | |||||
| ! sendChangeOnlyOnRelease, false, true); | |||||
| if (e.mods.isShiftDown()) | if (e.mods.isShiftDown()) | ||||
| setMinValue (getMaxValue() - minMaxDiff, false); | |||||
| setMinValue (getMaxValue() - minMaxDiff, false, false, true); | |||||
| else | else | ||||
| minMaxDiff = valueMax - valueMin; | minMaxDiff = valueMax - valueMin; | ||||
| } | } | ||||
| @@ -52151,6 +52190,7 @@ TreeViewItem::TreeViewItem() | |||||
| selected (false), | selected (false), | ||||
| redrawNeeded (true), | redrawNeeded (true), | ||||
| drawLinesInside (true), | drawLinesInside (true), | ||||
| drawsInLeftMargin (false), | |||||
| openness (opennessDefault) | openness (opennessDefault) | ||||
| { | { | ||||
| static int nextUID = 0; | static int nextUID = 0; | ||||
| @@ -52425,6 +52465,11 @@ int TreeViewItem::getIndentX() const throw() | |||||
| return x; | return x; | ||||
| } | } | ||||
| void TreeViewItem::setDrawsInLeftMargin (bool canDrawInLeftMargin) throw() | |||||
| { | |||||
| drawsInLeftMargin = canDrawInLeftMargin; | |||||
| } | |||||
| void TreeViewItem::paintRecursively (Graphics& g, int width) | void TreeViewItem::paintRecursively (Graphics& g, int width) | ||||
| { | { | ||||
| jassert (ownerView != 0); | jassert (ownerView != 0); | ||||
| @@ -52499,7 +52544,8 @@ void TreeViewItem::paintRecursively (Graphics& g, int width) | |||||
| g.saveState(); | g.saveState(); | ||||
| g.setOrigin (indent, 0); | g.setOrigin (indent, 0); | ||||
| if (g.reduceClipRegion (0, 0, itemW, itemHeight)) | |||||
| if (g.reduceClipRegion (drawsInLeftMargin ? -indent : 0, 0, | |||||
| drawsInLeftMargin ? itemW + indent : itemW, itemHeight)) | |||||
| paintItem (g, itemW, itemHeight); | paintItem (g, itemW, itemHeight); | ||||
| g.restoreState(); | g.restoreState(); | ||||
| @@ -56669,6 +56715,14 @@ void ComponentBoundsConstrainer::setBoundsForComponent (Component* const compone | |||||
| applyBoundsToComponent (component, x, y, w, h); | applyBoundsToComponent (component, x, y, w, h); | ||||
| } | } | ||||
| void ComponentBoundsConstrainer::checkComponentBounds (Component* component) | |||||
| { | |||||
| setBoundsForComponent (component, | |||||
| component->getX(), component->getY(), | |||||
| component->getWidth(), component->getHeight(), | |||||
| false, false, false, false); | |||||
| } | |||||
| void ComponentBoundsConstrainer::applyBoundsToComponent (Component* component, | void ComponentBoundsConstrainer::applyBoundsToComponent (Component* component, | ||||
| int x, int y, int w, int h) | int x, int y, int w, int h) | ||||
| { | { | ||||
| @@ -58996,7 +59050,7 @@ const StringArray TabbedButtonBar::getTabNames() const | |||||
| return tabs; | return tabs; | ||||
| } | } | ||||
| void TabbedButtonBar::setCurrentTabIndex (int newIndex) | |||||
| void TabbedButtonBar::setCurrentTabIndex (int newIndex, const bool sendChangeMessage_) | |||||
| { | { | ||||
| if (currentTabIndex != newIndex) | if (currentTabIndex != newIndex) | ||||
| { | { | ||||
| @@ -59014,7 +59068,9 @@ void TabbedButtonBar::setCurrentTabIndex (int newIndex) | |||||
| } | } | ||||
| resized(); | resized(); | ||||
| sendChangeMessage (this); | |||||
| if (sendChangeMessage_) | |||||
| sendChangeMessage (this); | |||||
| currentTabChanged (newIndex, newIndex >= 0 ? tabs [newIndex] : String::empty); | currentTabChanged (newIndex, newIndex >= 0 ? tabs [newIndex] : String::empty); | ||||
| } | } | ||||
| @@ -59396,9 +59452,9 @@ void TabbedComponent::setTabBackgroundColour (const int tabIndex, const Colour& | |||||
| repaint(); | repaint(); | ||||
| } | } | ||||
| void TabbedComponent::setCurrentTabIndex (const int newTabIndex) | |||||
| void TabbedComponent::setCurrentTabIndex (const int newTabIndex, const bool sendChangeMessage) | |||||
| { | { | ||||
| tabs->setCurrentTabIndex (newTabIndex); | |||||
| tabs->setCurrentTabIndex (newTabIndex, sendChangeMessage); | |||||
| } | } | ||||
| int TabbedComponent::getCurrentTabIndex() const | int TabbedComponent::getCurrentTabIndex() const | ||||
| @@ -61369,8 +61425,11 @@ void LookAndFeel::drawImageButton (Graphics& g, Image* image, | |||||
| int imageX, int imageY, int imageW, int imageH, | int imageX, int imageY, int imageW, int imageH, | ||||
| const Colour& overlayColour, | const Colour& overlayColour, | ||||
| float imageOpacity, | float imageOpacity, | ||||
| ImageButton& /*button*/) | |||||
| ImageButton& button) | |||||
| { | { | ||||
| if (! button.isEnabled()) | |||||
| imageOpacity *= 0.3f; | |||||
| if (! overlayColour.isOpaque()) | if (! overlayColour.isOpaque()) | ||||
| { | { | ||||
| g.setOpacity (imageOpacity); | g.setOpacity (imageOpacity); | ||||
| @@ -71847,6 +71906,8 @@ ComponentPeer::~ComponentPeer() | |||||
| { | { | ||||
| heavyweightPeers.removeValue (this); | heavyweightPeers.removeValue (this); | ||||
| delete dragAndDropTargetComponent; | delete dragAndDropTargetComponent; | ||||
| Desktop::getInstance().triggerFocusCallback(); | |||||
| } | } | ||||
| int ComponentPeer::getNumPeers() throw() | int ComponentPeer::getNumPeers() throw() | ||||
| @@ -76119,7 +76180,8 @@ void Graphics::drawBevel (const int x, | |||||
| const int bevelThickness, | const int bevelThickness, | ||||
| const Colour& topLeftColour, | const Colour& topLeftColour, | ||||
| const Colour& bottomRightColour, | const Colour& bottomRightColour, | ||||
| const bool useGradient) const throw() | |||||
| const bool useGradient, | |||||
| const bool sharpEdgeOnOutside) const throw() | |||||
| { | { | ||||
| // passing in a silly number can cause maths problems in rendering! | // passing in a silly number can cause maths problems in rendering! | ||||
| ASSERT_COORDS_ARE_SENSIBLE_NUMBERS (x, y, width, height); | ASSERT_COORDS_ARE_SENSIBLE_NUMBERS (x, y, width, height); | ||||
| @@ -76131,7 +76193,7 @@ void Graphics::drawBevel (const int x, | |||||
| for (int i = bevelThickness; --i >= 0;) | for (int i = bevelThickness; --i >= 0;) | ||||
| { | { | ||||
| const float op = useGradient ? ramp * (bevelThickness - i) | |||||
| const float op = useGradient ? ramp * (sharpEdgeOnOutside ? bevelThickness - i : i) | |||||
| : oldOpacity; | : oldOpacity; | ||||
| context->fillRectWithColour (x + i, y + i, width - i * 2, 1, topLeftColour.withMultipliedAlpha (op), false); | context->fillRectWithColour (x + i, y + i, width - i * 2, 1, topLeftColour.withMultipliedAlpha (op), false); | ||||
| @@ -213882,14 +213944,14 @@ Image* juce_loadJPEGImageFromStream (InputStream& in) throw() | |||||
| } | } | ||||
| jpeg_finish_decompress (&jpegDecompStruct); | jpeg_finish_decompress (&jpegDecompStruct); | ||||
| in.setPosition (((char*) jpegDecompStruct.src->next_input_byte) - (char*) mb.getData()); | |||||
| } | } | ||||
| jpeg_destroy_decompress (&jpegDecompStruct); | jpeg_destroy_decompress (&jpegDecompStruct); | ||||
| } | } | ||||
| catch (...) | catch (...) | ||||
| {} | {} | ||||
| in.setPosition (((char*) jpegDecompStruct.src->next_input_byte) - (char*) mb.getData()); | |||||
| } | } | ||||
| return image; | return image; | ||||
| @@ -254840,12 +254902,10 @@ bool juce_canWriteToFile (const String& fileName) throw() | |||||
| bool juce_deleteFile (const String& fileName) throw() | bool juce_deleteFile (const String& fileName) throw() | ||||
| { | { | ||||
| const char* const fileNameUTF8 = fileName.toUTF8(); | |||||
| if (juce_isDirectory (fileName)) | if (juce_isDirectory (fileName)) | ||||
| return rmdir (fileNameUTF8) == 0; | |||||
| return rmdir ((const char*) fileName.toUTF8()) == 0; | |||||
| else | else | ||||
| return remove (fileNameUTF8) == 0; | |||||
| return remove ((const char*) fileName.toUTF8()) == 0; | |||||
| } | } | ||||
| bool juce_moveFile (const String& source, const String& dest) throw() | bool juce_moveFile (const String& source, const String& dest) throw() | ||||
| @@ -254872,14 +254932,13 @@ void juce_createDirectory (const String& fileName) throw() | |||||
| void* juce_fileOpen (const String& fileName, bool forWriting) throw() | void* juce_fileOpen (const String& fileName, bool forWriting) throw() | ||||
| { | { | ||||
| const char* const fileNameUTF8 = fileName.toUTF8(); | |||||
| int flags = O_RDONLY; | int flags = O_RDONLY; | ||||
| if (forWriting) | if (forWriting) | ||||
| { | { | ||||
| if (juce_fileExists (fileName, false)) | if (juce_fileExists (fileName, false)) | ||||
| { | { | ||||
| const int f = open (fileNameUTF8, O_RDWR, 00644); | |||||
| const int f = open ((const char*) fileName.toUTF8(), O_RDWR, 00644); | |||||
| if (f != -1) | if (f != -1) | ||||
| lseek (f, 0, SEEK_END); | lseek (f, 0, SEEK_END); | ||||
| @@ -254892,7 +254951,7 @@ void* juce_fileOpen (const String& fileName, bool forWriting) throw() | |||||
| } | } | ||||
| } | } | ||||
| return (void*) open (fileNameUTF8, flags, 00644); | |||||
| return (void*) open ((const char*) fileName.toUTF8(), flags, 00644); | |||||
| } | } | ||||
| void juce_fileClose (void* handle) throw() | void juce_fileClose (void* handle) throw() | ||||
| @@ -263836,6 +263895,8 @@ const String PlatformUtilities::convertToPrecomposedUnicode (const String& s) | |||||
| return result; | return result; | ||||
| } | } | ||||
| #if ! JUCE_ONLY_BUILD_CORE_LIBRARY | |||||
| void SystemClipboard::copyTextToClipboard (const String& text) throw() | void SystemClipboard::copyTextToClipboard (const String& text) throw() | ||||
| { | { | ||||
| [[NSPasteboard generalPasteboard] declareTypes: [NSArray arrayWithObject: NSStringPboardType] | [[NSPasteboard generalPasteboard] declareTypes: [NSArray arrayWithObject: NSStringPboardType] | ||||
| @@ -263853,6 +263914,8 @@ const String SystemClipboard::getTextFromClipboard() throw() | |||||
| : nsStringToJuce (text); | : nsStringToJuce (text); | ||||
| } | } | ||||
| #endif | |||||
| #endif | #endif | ||||
| /********* End of inlined file: juce_mac_Strings.mm *********/ | /********* End of inlined file: juce_mac_Strings.mm *********/ | ||||
| @@ -264844,12 +264907,10 @@ bool juce_canWriteToFile (const String& fileName) throw() | |||||
| bool juce_deleteFile (const String& fileName) throw() | bool juce_deleteFile (const String& fileName) throw() | ||||
| { | { | ||||
| const char* const fileNameUTF8 = fileName.toUTF8(); | |||||
| if (juce_isDirectory (fileName)) | if (juce_isDirectory (fileName)) | ||||
| return rmdir (fileNameUTF8) == 0; | |||||
| return rmdir ((const char*) fileName.toUTF8()) == 0; | |||||
| else | else | ||||
| return remove (fileNameUTF8) == 0; | |||||
| return remove ((const char*) fileName.toUTF8()) == 0; | |||||
| } | } | ||||
| bool juce_moveFile (const String& source, const String& dest) throw() | bool juce_moveFile (const String& source, const String& dest) throw() | ||||
| @@ -264876,14 +264937,13 @@ void juce_createDirectory (const String& fileName) throw() | |||||
| void* juce_fileOpen (const String& fileName, bool forWriting) throw() | void* juce_fileOpen (const String& fileName, bool forWriting) throw() | ||||
| { | { | ||||
| const char* const fileNameUTF8 = fileName.toUTF8(); | |||||
| int flags = O_RDONLY; | int flags = O_RDONLY; | ||||
| if (forWriting) | if (forWriting) | ||||
| { | { | ||||
| if (juce_fileExists (fileName, false)) | if (juce_fileExists (fileName, false)) | ||||
| { | { | ||||
| const int f = open (fileNameUTF8, O_RDWR, 00644); | |||||
| const int f = open ((const char*) fileName.toUTF8(), O_RDWR, 00644); | |||||
| if (f != -1) | if (f != -1) | ||||
| lseek (f, 0, SEEK_END); | lseek (f, 0, SEEK_END); | ||||
| @@ -264896,7 +264956,7 @@ void* juce_fileOpen (const String& fileName, bool forWriting) throw() | |||||
| } | } | ||||
| } | } | ||||
| return (void*) open (fileNameUTF8, flags, 00644); | |||||
| return (void*) open ((const char*) fileName.toUTF8(), flags, 00644); | |||||
| } | } | ||||
| void juce_fileClose (void* handle) throw() | void juce_fileClose (void* handle) throw() | ||||
| @@ -265665,6 +265725,8 @@ void PlatformUtilities::beep() | |||||
| NSBeep(); | NSBeep(); | ||||
| } | } | ||||
| #if ! JUCE_ONLY_BUILD_CORE_LIBRARY | |||||
| bool AlertWindow::showNativeDialogBox (const String& title, | bool AlertWindow::showNativeDialogBox (const String& title, | ||||
| const String& bodyText, | const String& bodyText, | ||||
| bool isOkCancel) | bool isOkCancel) | ||||
| @@ -265851,6 +265913,9 @@ void juce_updateMultiMonitorInfo (Array <Rectangle>& monitorCoords, const bool c | |||||
| } | } | ||||
| #endif | #endif | ||||
| #endif | |||||
| /********* End of inlined file: juce_mac_MiscUtilities.mm *********/ | /********* End of inlined file: juce_mac_MiscUtilities.mm *********/ | ||||
| /********* Start of inlined file: juce_mac_Debugging.mm *********/ | /********* Start of inlined file: juce_mac_Debugging.mm *********/ | ||||
| @@ -268784,6 +268849,9 @@ bool QuickTimeMovieComponent::isQuickTimeAvailable() throw() | |||||
| static QTMovie* openMovieFromStream (InputStream* movieStream, File& movieFile) | static QTMovie* openMovieFromStream (InputStream* movieStream, File& movieFile) | ||||
| { | { | ||||
| // unfortunately, QTMovie objects can only be created on the main thread.. | |||||
| jassert (MessageManager::getInstance()->isThisTheMessageThread()); | |||||
| QTMovie* movie = 0; | QTMovie* movie = 0; | ||||
| FileInputStream* const fin = dynamic_cast <FileInputStream*> (movieStream); | FileInputStream* const fin = dynamic_cast <FileInputStream*> (movieStream); | ||||
| @@ -7309,8 +7309,11 @@ public: | |||||
| /** Converts the array to a number string. | /** Converts the array to a number string. | ||||
| Specify a base such as 2 (binary), 8 (octal), 10 (decimal), 16 (hex). | Specify a base such as 2 (binary), 8 (octal), 10 (decimal), 16 (hex). | ||||
| If minuimumNumCharacters is greater than 0, the returned string will be | |||||
| padded with leading zeros to reach at least that length. | |||||
| */ | */ | ||||
| const String toString (const int base) const throw(); | |||||
| const String toString (const int base, const int minimumNumCharacters = 1) const throw(); | |||||
| /** Converts a number string to an array. | /** Converts a number string to an array. | ||||
| @@ -8107,6 +8110,12 @@ public: | |||||
| */ | */ | ||||
| void setIgnoresCase (const bool shouldIgnoreCase) throw(); | void setIgnoresCase (const bool shouldIgnoreCase) throw(); | ||||
| /** Returns a descriptive string containing the items. | |||||
| This is handy for dumping the contents of an array. | |||||
| */ | |||||
| const String getDescription() const; | |||||
| /** Reduces the amount of storage being used by the array. | /** Reduces the amount of storage being used by the array. | ||||
| Arrays typically allocate slightly more storage than they need, and after | Arrays typically allocate slightly more storage than they need, and after | ||||
| @@ -19582,6 +19591,11 @@ public: | |||||
| The top-left colour is used for the top- and left-hand edges of the | The top-left colour is used for the top- and left-hand edges of the | ||||
| bevel; the bottom-right colour is used for the bottom- and right-hand | bevel; the bottom-right colour is used for the bottom- and right-hand | ||||
| edges. | edges. | ||||
| If useGradient is true, then the bevel fades out to make it look more curved | |||||
| and less angular. If sharpEdgeOnOutside is true, the outside of the bevel is | |||||
| sharp, and it fades towards the centre; if sharpEdgeOnOutside is false, then | |||||
| the centre edges are sharp and it fades towards the outside. | |||||
| */ | */ | ||||
| void drawBevel (const int x, | void drawBevel (const int x, | ||||
| const int y, | const int y, | ||||
| @@ -19590,7 +19604,8 @@ public: | |||||
| const int bevelThickness, | const int bevelThickness, | ||||
| const Colour& topLeftColour = Colours::white, | const Colour& topLeftColour = Colours::white, | ||||
| const Colour& bottomRightColour = Colours::black, | const Colour& bottomRightColour = Colours::black, | ||||
| const bool useGradient = true) const throw(); | |||||
| const bool useGradient = true, | |||||
| const bool sharpEdgeOnOutside = true) const throw(); | |||||
| /** Draws a pixel using the current colour or brush. | /** Draws a pixel using the current colour or brush. | ||||
| */ | */ | ||||
| @@ -37968,7 +37983,7 @@ public: | |||||
| { | { | ||||
| MessageManagerLock mml (Thread::getCurrentThread()); | MessageManagerLock mml (Thread::getCurrentThread()); | ||||
| if (! mml.lockWasGained) | |||||
| if (! mml.lockWasGained()) | |||||
| return; // another thread is trying to kill us! | return; // another thread is trying to kill us! | ||||
| ..do some locked stuff here.. | ..do some locked stuff here.. | ||||
| @@ -43250,6 +43265,21 @@ public: | |||||
| */ | */ | ||||
| virtual const String getDragSourceDescription(); | virtual const String getDragSourceDescription(); | ||||
| /** Sets a flag to indicate that the item wants to be allowed | |||||
| to draw all the way across to the left edge of the treeview. | |||||
| By default this is false, which means that when the paintItem() | |||||
| method is called, its graphics context is clipped to only allow | |||||
| drawing within the item's rectangle. If this flag is set to true, | |||||
| then the graphics context isn't clipped on its left side, so it | |||||
| can draw all the way across to the left margin. Note that the | |||||
| context will still have its origin in the same place though, so | |||||
| the coordinates of anything to its left will be negative. It's | |||||
| mostly useful if you want to draw a wider bar behind the | |||||
| highlighted item. | |||||
| */ | |||||
| void setDrawsInLeftMargin (bool canDrawInLeftMargin) throw(); | |||||
| juce_UseDebuggingNewOperator | juce_UseDebuggingNewOperator | ||||
| private: | private: | ||||
| @@ -43261,6 +43291,7 @@ private: | |||||
| bool selected : 1; | bool selected : 1; | ||||
| bool redrawNeeded : 1; | bool redrawNeeded : 1; | ||||
| bool drawLinesInside : 1; | bool drawLinesInside : 1; | ||||
| bool drawsInLeftMargin : 1; | |||||
| unsigned int openness : 2; | unsigned int openness : 2; | ||||
| friend class TreeView; | friend class TreeView; | ||||
| @@ -44025,6 +44056,11 @@ public: | |||||
| const bool isStretchingBottom, | const bool isStretchingBottom, | ||||
| const bool isStretchingRight); | const bool isStretchingRight); | ||||
| /** Performs a check on the current size of a component, and moves or resizes | |||||
| it if it fails the constraints. | |||||
| */ | |||||
| void checkComponentBounds (Component* component); | |||||
| /** Called by setBoundsForComponent() to apply a new constrained size to a | /** Called by setBoundsForComponent() to apply a new constrained size to a | ||||
| component. | component. | ||||
| @@ -45311,18 +45347,22 @@ public: | |||||
| want to handle it. | want to handle it. | ||||
| @param newValue the new value to set - this will be restricted by the | @param newValue the new value to set - this will be restricted by the | ||||
| minimum and maximum range, and the max value (in a two-value | |||||
| slider) or the mid value (in a three-value slider), and | |||||
| will be snapped to the nearest interval if one has been set. | |||||
| minimum and maximum range, and will be snapped to the nearest | |||||
| interval if one has been set. | |||||
| @param sendUpdateMessage if false, a change to the value will not trigger a call to | @param sendUpdateMessage if false, a change to the value will not trigger a call to | ||||
| any SliderListeners or the valueChanged() method | any SliderListeners or the valueChanged() method | ||||
| @param sendMessageSynchronously if true, then a call to the SliderListeners will be made | @param sendMessageSynchronously if true, then a call to the SliderListeners will be made | ||||
| synchronously; if false, it will be asynchronous | synchronously; if false, it will be asynchronous | ||||
| @param allowNudgingOfOtherValues if false, this value will be restricted to being below the | |||||
| max value (in a two-value slider) or the mid value (in a three-value | |||||
| slider). If false, then if this value goes beyond those values, | |||||
| it will push them along with it. | |||||
| @see getMinValue, setMaxValue, setValue | @see getMinValue, setMaxValue, setValue | ||||
| */ | */ | ||||
| void setMinValue (double newValue, | void setMinValue (double newValue, | ||||
| const bool sendUpdateMessage = true, | const bool sendUpdateMessage = true, | ||||
| const bool sendMessageSynchronously = false); | |||||
| const bool sendMessageSynchronously = false, | |||||
| const bool allowNudgingOfOtherValues = false); | |||||
| /** For a slider with two or three thumbs, this returns the higher of its values. | /** For a slider with two or three thumbs, this returns the higher of its values. | ||||
| @@ -45341,18 +45381,22 @@ public: | |||||
| want to handle it. | want to handle it. | ||||
| @param newValue the new value to set - this will be restricted by the | @param newValue the new value to set - this will be restricted by the | ||||
| minimum and maximum range, and the max value (in a two-value | |||||
| slider) or the mid value (in a three-value slider), and | |||||
| will be snapped to the nearest interval if one has been set. | |||||
| minimum and maximum range, and will be snapped to the nearest | |||||
| interval if one has been set. | |||||
| @param sendUpdateMessage if false, a change to the value will not trigger a call to | @param sendUpdateMessage if false, a change to the value will not trigger a call to | ||||
| any SliderListeners or the valueChanged() method | any SliderListeners or the valueChanged() method | ||||
| @param sendMessageSynchronously if true, then a call to the SliderListeners will be made | @param sendMessageSynchronously if true, then a call to the SliderListeners will be made | ||||
| synchronously; if false, it will be asynchronous | synchronously; if false, it will be asynchronous | ||||
| @param allowNudgingOfOtherValues if false, this value will be restricted to being above the | |||||
| min value (in a two-value slider) or the mid value (in a three-value | |||||
| slider). If false, then if this value goes beyond those values, | |||||
| it will push them along with it. | |||||
| @see getMaxValue, setMinValue, setValue | @see getMaxValue, setMinValue, setValue | ||||
| */ | */ | ||||
| void setMaxValue (double newValue, | void setMaxValue (double newValue, | ||||
| const bool sendUpdateMessage = true, | const bool sendUpdateMessage = true, | ||||
| const bool sendMessageSynchronously = false); | |||||
| const bool sendMessageSynchronously = false, | |||||
| const bool allowNudgingOfOtherValues = false); | |||||
| /** Adds a listener to be called when this slider's value changes. */ | /** Adds a listener to be called when this slider's value changes. */ | ||||
| void addListener (SliderListener* const listener) throw(); | void addListener (SliderListener* const listener) throw(); | ||||
| @@ -45625,6 +45669,7 @@ private: | |||||
| int velocityModeThreshold; | int velocityModeThreshold; | ||||
| float rotaryStart, rotaryEnd; | float rotaryStart, rotaryEnd; | ||||
| int numDecimalPlaces, mouseXWhenLastDragged, mouseYWhenLastDragged; | int numDecimalPlaces, mouseXWhenLastDragged, mouseYWhenLastDragged; | ||||
| int mouseDragStartX, mouseDragStartY; | |||||
| int sliderRegionStart, sliderRegionSize; | int sliderRegionStart, sliderRegionSize; | ||||
| int sliderBeingDragged; | int sliderBeingDragged; | ||||
| int pixelsForFullDragExtent; | int pixelsForFullDragExtent; | ||||
| @@ -47134,7 +47179,7 @@ public: | |||||
| To deselect all the tabs, use an index of -1. | To deselect all the tabs, use an index of -1. | ||||
| */ | */ | ||||
| void setCurrentTabIndex (int newTabIndex); | |||||
| void setCurrentTabIndex (int newTabIndex, const bool sendChangeMessage = true); | |||||
| /** Returns the name of the currently selected tab. | /** Returns the name of the currently selected tab. | ||||
| @@ -47353,7 +47398,7 @@ public: | |||||
| @see TabbedButtonBar::setCurrentTabIndex | @see TabbedButtonBar::setCurrentTabIndex | ||||
| */ | */ | ||||
| void setCurrentTabIndex (const int newTabIndex); | |||||
| void setCurrentTabIndex (const int newTabIndex, const bool sendChangeMessage = true); | |||||
| /** Returns the index of the currently selected tab. | /** Returns the index of the currently selected tab. | ||||
| @@ -66,7 +66,7 @@ | |||||
| #pragma warning (disable: 4309 4305) | #pragma warning (disable: 4309 4305) | ||||
| #endif | #endif | ||||
| #if JUCE_MAC && JUCE_32BIT && JUCE_SUPPORT_CARBON | |||||
| #if JUCE_MAC && JUCE_32BIT && JUCE_SUPPORT_CARBON && ! JUCE_ONLY_BUILD_CORE_LIBRARY | |||||
| BEGIN_JUCE_NAMESPACE | BEGIN_JUCE_NAMESPACE | ||||
| #include "../build/macosx/platform_specific_code/juce_mac_CarbonViewWrapperComponent.h" | #include "../build/macosx/platform_specific_code/juce_mac_CarbonViewWrapperComponent.h" | ||||
| END_JUCE_NAMESPACE | END_JUCE_NAMESPACE | ||||
| @@ -97,8 +97,6 @@ public: | |||||
| #ifdef WIN32 | #ifdef WIN32 | ||||
| if (InitializeQTML (0) != noErr) | if (InitializeQTML (0) != noErr) | ||||
| return; | return; | ||||
| #elif JUCE_MAC | |||||
| EnterMoviesOnThread (0); | |||||
| #endif | #endif | ||||
| if (EnterMovies() != noErr) | if (EnterMovies() != noErr) | ||||
| return; | return; | ||||
| @@ -279,7 +279,7 @@ public: | |||||
| { | { | ||||
| MessageManagerLock mml (Thread::getCurrentThread()); | MessageManagerLock mml (Thread::getCurrentThread()); | ||||
| if (! mml.lockWasGained) | |||||
| if (! mml.lockWasGained()) | |||||
| return; // another thread is trying to kill us! | return; // another thread is trying to kill us! | ||||
| ..do some locked stuff here.. | ..do some locked stuff here.. | ||||
| @@ -1,242 +1,242 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||||
| Copyright 2004-7 by Raw Material Software ltd. | |||||
| ------------------------------------------------------------------------------ | |||||
| JUCE can be redistributed and/or modified under the terms of the | |||||
| GNU General Public License, as published by the Free Software Foundation; | |||||
| either version 2 of the License, or (at your option) any later version. | |||||
| JUCE is distributed in the hope that it will be useful, | |||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| GNU General Public License for more details. | |||||
| You should have received a copy of the GNU General Public License | |||||
| along with JUCE; if not, visit www.gnu.org/licenses or write to the | |||||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||||
| Boston, MA 02111-1307 USA | |||||
| ------------------------------------------------------------------------------ | |||||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||||
| more information. | |||||
| ============================================================================== | |||||
| */ | |||||
| #include "../../../../juce_core/basics/juce_StandardHeader.h" | |||||
| BEGIN_JUCE_NAMESPACE | |||||
| #include "juce_ImageButton.h" | |||||
| #include "../../graphics/imaging/juce_ImageCache.h" | |||||
| #include "../lookandfeel/juce_LookAndFeel.h" | |||||
| //============================================================================== | |||||
| ImageButton::ImageButton (const String& text) | |||||
| : Button (text), | |||||
| scaleImageToFit (true), | |||||
| preserveProportions (true), | |||||
| alphaThreshold (0), | |||||
| imageX (0), | |||||
| imageY (0), | |||||
| imageW (0), | |||||
| imageH (0), | |||||
| normalImage (0), | |||||
| overImage (0), | |||||
| downImage (0) | |||||
| { | |||||
| } | |||||
| ImageButton::~ImageButton() | |||||
| { | |||||
| deleteImages(); | |||||
| } | |||||
| void ImageButton::deleteImages() | |||||
| { | |||||
| if (normalImage != 0) | |||||
| { | |||||
| if (ImageCache::isImageInCache (normalImage)) | |||||
| ImageCache::release (normalImage); | |||||
| else | |||||
| delete normalImage; | |||||
| } | |||||
| if (overImage != 0) | |||||
| { | |||||
| if (ImageCache::isImageInCache (overImage)) | |||||
| ImageCache::release (overImage); | |||||
| else | |||||
| delete overImage; | |||||
| } | |||||
| if (downImage != 0) | |||||
| { | |||||
| if (ImageCache::isImageInCache (downImage)) | |||||
| ImageCache::release (downImage); | |||||
| else | |||||
| delete downImage; | |||||
| } | |||||
| } | |||||
| void ImageButton::setImages (const bool resizeButtonNowToFitThisImage, | |||||
| const bool rescaleImagesWhenButtonSizeChanges, | |||||
| const bool preserveImageProportions, | |||||
| Image* const normalImage_, | |||||
| const float imageOpacityWhenNormal, | |||||
| const Colour& overlayColourWhenNormal, | |||||
| Image* const overImage_, | |||||
| const float imageOpacityWhenOver, | |||||
| const Colour& overlayColourWhenOver, | |||||
| Image* const downImage_, | |||||
| const float imageOpacityWhenDown, | |||||
| const Colour& overlayColourWhenDown, | |||||
| const float hitTestAlphaThreshold) | |||||
| { | |||||
| deleteImages(); | |||||
| normalImage = normalImage_; | |||||
| overImage = overImage_; | |||||
| downImage = downImage_; | |||||
| if (resizeButtonNowToFitThisImage && normalImage != 0) | |||||
| { | |||||
| imageW = normalImage->getWidth(); | |||||
| imageH = normalImage->getHeight(); | |||||
| setSize (imageW, imageH); | |||||
| } | |||||
| scaleImageToFit = rescaleImagesWhenButtonSizeChanges; | |||||
| preserveProportions = preserveImageProportions; | |||||
| normalOpacity = imageOpacityWhenNormal; | |||||
| normalOverlay = overlayColourWhenNormal; | |||||
| overOpacity = imageOpacityWhenOver; | |||||
| overOverlay = overlayColourWhenOver; | |||||
| downOpacity = imageOpacityWhenDown; | |||||
| downOverlay = overlayColourWhenDown; | |||||
| alphaThreshold = (unsigned char) jlimit (0, 0xff, roundFloatToInt (255.0f * hitTestAlphaThreshold)); | |||||
| repaint(); | |||||
| } | |||||
| Image* ImageButton::getCurrentImage() const | |||||
| { | |||||
| if (isDown()) | |||||
| return getDownImage(); | |||||
| if (isOver()) | |||||
| return getOverImage(); | |||||
| return getNormalImage(); | |||||
| } | |||||
| Image* ImageButton::getNormalImage() const throw() | |||||
| { | |||||
| return normalImage; | |||||
| } | |||||
| Image* ImageButton::getOverImage() const throw() | |||||
| { | |||||
| return (overImage != 0) ? overImage | |||||
| : normalImage; | |||||
| } | |||||
| Image* ImageButton::getDownImage() const throw() | |||||
| { | |||||
| return (downImage != 0) ? downImage | |||||
| : getOverImage(); | |||||
| } | |||||
| void ImageButton::paintButton (Graphics& g, | |||||
| bool isMouseOverButton, | |||||
| bool isButtonDown) | |||||
| { | |||||
| if (! isEnabled()) | |||||
| { | |||||
| isMouseOverButton = false; | |||||
| isButtonDown = false; | |||||
| } | |||||
| Image* const im = getCurrentImage(); | |||||
| if (im != 0) | |||||
| { | |||||
| const int iw = im->getWidth(); | |||||
| const int ih = im->getHeight(); | |||||
| imageW = getWidth(); | |||||
| imageH = getHeight(); | |||||
| imageX = (imageW - iw) >> 1; | |||||
| imageY = (imageH - ih) >> 1; | |||||
| if (scaleImageToFit) | |||||
| { | |||||
| if (preserveProportions) | |||||
| { | |||||
| int newW, newH; | |||||
| const float imRatio = ih / (float)iw; | |||||
| const float destRatio = imageH / (float)imageW; | |||||
| if (imRatio > destRatio) | |||||
| { | |||||
| newW = roundFloatToInt (imageH / imRatio); | |||||
| newH = imageH; | |||||
| } | |||||
| else | |||||
| { | |||||
| newW = imageW; | |||||
| newH = roundFloatToInt (imageW * imRatio); | |||||
| } | |||||
| imageX = (imageW - newW) / 2; | |||||
| imageY = (imageH - newH) / 2; | |||||
| imageW = newW; | |||||
| imageH = newH; | |||||
| } | |||||
| else | |||||
| { | |||||
| imageX = 0; | |||||
| imageY = 0; | |||||
| } | |||||
| } | |||||
| if (! scaleImageToFit) | |||||
| { | |||||
| imageW = iw; | |||||
| imageH = ih; | |||||
| } | |||||
| getLookAndFeel().drawImageButton (g, im, imageX, imageY, imageW, imageH, | |||||
| isButtonDown ? downOverlay | |||||
| : (isMouseOverButton ? overOverlay | |||||
| : normalOverlay), | |||||
| isButtonDown ? downOpacity | |||||
| : (isMouseOverButton ? overOpacity | |||||
| : normalOpacity), | |||||
| *this); | |||||
| } | |||||
| } | |||||
| bool ImageButton::hitTest (int x, int y) | |||||
| { | |||||
| if (alphaThreshold == 0) | |||||
| return true; | |||||
| Image* const im = getCurrentImage(); | |||||
| return im == 0 | |||||
| || (imageW > 0 && imageH > 0 | |||||
| && alphaThreshold < im->getPixelAt (((x - imageX) * im->getWidth()) / imageW, | |||||
| ((y - imageY) * im->getHeight()) / imageH).getAlpha()); | |||||
| } | |||||
| END_JUCE_NAMESPACE | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||||
| Copyright 2004-7 by Raw Material Software ltd. | |||||
| ------------------------------------------------------------------------------ | |||||
| JUCE can be redistributed and/or modified under the terms of the | |||||
| GNU General Public License, as published by the Free Software Foundation; | |||||
| either version 2 of the License, or (at your option) any later version. | |||||
| JUCE is distributed in the hope that it will be useful, | |||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| GNU General Public License for more details. | |||||
| You should have received a copy of the GNU General Public License | |||||
| along with JUCE; if not, visit www.gnu.org/licenses or write to the | |||||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||||
| Boston, MA 02111-1307 USA | |||||
| ------------------------------------------------------------------------------ | |||||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||||
| more information. | |||||
| ============================================================================== | |||||
| */ | |||||
| #include "../../../../juce_core/basics/juce_StandardHeader.h" | |||||
| BEGIN_JUCE_NAMESPACE | |||||
| #include "juce_ImageButton.h" | |||||
| #include "../../graphics/imaging/juce_ImageCache.h" | |||||
| #include "../lookandfeel/juce_LookAndFeel.h" | |||||
| //============================================================================== | |||||
| ImageButton::ImageButton (const String& text) | |||||
| : Button (text), | |||||
| scaleImageToFit (true), | |||||
| preserveProportions (true), | |||||
| alphaThreshold (0), | |||||
| imageX (0), | |||||
| imageY (0), | |||||
| imageW (0), | |||||
| imageH (0), | |||||
| normalImage (0), | |||||
| overImage (0), | |||||
| downImage (0) | |||||
| { | |||||
| } | |||||
| ImageButton::~ImageButton() | |||||
| { | |||||
| deleteImages(); | |||||
| } | |||||
| void ImageButton::deleteImages() | |||||
| { | |||||
| if (normalImage != 0) | |||||
| { | |||||
| if (ImageCache::isImageInCache (normalImage)) | |||||
| ImageCache::release (normalImage); | |||||
| else | |||||
| delete normalImage; | |||||
| } | |||||
| if (overImage != 0) | |||||
| { | |||||
| if (ImageCache::isImageInCache (overImage)) | |||||
| ImageCache::release (overImage); | |||||
| else | |||||
| delete overImage; | |||||
| } | |||||
| if (downImage != 0) | |||||
| { | |||||
| if (ImageCache::isImageInCache (downImage)) | |||||
| ImageCache::release (downImage); | |||||
| else | |||||
| delete downImage; | |||||
| } | |||||
| } | |||||
| void ImageButton::setImages (const bool resizeButtonNowToFitThisImage, | |||||
| const bool rescaleImagesWhenButtonSizeChanges, | |||||
| const bool preserveImageProportions, | |||||
| Image* const normalImage_, | |||||
| const float imageOpacityWhenNormal, | |||||
| const Colour& overlayColourWhenNormal, | |||||
| Image* const overImage_, | |||||
| const float imageOpacityWhenOver, | |||||
| const Colour& overlayColourWhenOver, | |||||
| Image* const downImage_, | |||||
| const float imageOpacityWhenDown, | |||||
| const Colour& overlayColourWhenDown, | |||||
| const float hitTestAlphaThreshold) | |||||
| { | |||||
| deleteImages(); | |||||
| normalImage = normalImage_; | |||||
| overImage = overImage_; | |||||
| downImage = downImage_; | |||||
| if (resizeButtonNowToFitThisImage && normalImage != 0) | |||||
| { | |||||
| imageW = normalImage->getWidth(); | |||||
| imageH = normalImage->getHeight(); | |||||
| setSize (imageW, imageH); | |||||
| } | |||||
| scaleImageToFit = rescaleImagesWhenButtonSizeChanges; | |||||
| preserveProportions = preserveImageProportions; | |||||
| normalOpacity = imageOpacityWhenNormal; | |||||
| normalOverlay = overlayColourWhenNormal; | |||||
| overOpacity = imageOpacityWhenOver; | |||||
| overOverlay = overlayColourWhenOver; | |||||
| downOpacity = imageOpacityWhenDown; | |||||
| downOverlay = overlayColourWhenDown; | |||||
| alphaThreshold = (unsigned char) jlimit (0, 0xff, roundFloatToInt (255.0f * hitTestAlphaThreshold)); | |||||
| repaint(); | |||||
| } | |||||
| Image* ImageButton::getCurrentImage() const | |||||
| { | |||||
| if (isDown() || getToggleState()) | |||||
| return getDownImage(); | |||||
| if (isOver()) | |||||
| return getOverImage(); | |||||
| return getNormalImage(); | |||||
| } | |||||
| Image* ImageButton::getNormalImage() const throw() | |||||
| { | |||||
| return normalImage; | |||||
| } | |||||
| Image* ImageButton::getOverImage() const throw() | |||||
| { | |||||
| return (overImage != 0) ? overImage | |||||
| : normalImage; | |||||
| } | |||||
| Image* ImageButton::getDownImage() const throw() | |||||
| { | |||||
| return (downImage != 0) ? downImage | |||||
| : getOverImage(); | |||||
| } | |||||
| void ImageButton::paintButton (Graphics& g, | |||||
| bool isMouseOverButton, | |||||
| bool isButtonDown) | |||||
| { | |||||
| if (! isEnabled()) | |||||
| { | |||||
| isMouseOverButton = false; | |||||
| isButtonDown = false; | |||||
| } | |||||
| Image* const im = getCurrentImage(); | |||||
| if (im != 0) | |||||
| { | |||||
| const int iw = im->getWidth(); | |||||
| const int ih = im->getHeight(); | |||||
| imageW = getWidth(); | |||||
| imageH = getHeight(); | |||||
| imageX = (imageW - iw) >> 1; | |||||
| imageY = (imageH - ih) >> 1; | |||||
| if (scaleImageToFit) | |||||
| { | |||||
| if (preserveProportions) | |||||
| { | |||||
| int newW, newH; | |||||
| const float imRatio = ih / (float)iw; | |||||
| const float destRatio = imageH / (float)imageW; | |||||
| if (imRatio > destRatio) | |||||
| { | |||||
| newW = roundFloatToInt (imageH / imRatio); | |||||
| newH = imageH; | |||||
| } | |||||
| else | |||||
| { | |||||
| newW = imageW; | |||||
| newH = roundFloatToInt (imageW * imRatio); | |||||
| } | |||||
| imageX = (imageW - newW) / 2; | |||||
| imageY = (imageH - newH) / 2; | |||||
| imageW = newW; | |||||
| imageH = newH; | |||||
| } | |||||
| else | |||||
| { | |||||
| imageX = 0; | |||||
| imageY = 0; | |||||
| } | |||||
| } | |||||
| if (! scaleImageToFit) | |||||
| { | |||||
| imageW = iw; | |||||
| imageH = ih; | |||||
| } | |||||
| getLookAndFeel().drawImageButton (g, im, imageX, imageY, imageW, imageH, | |||||
| isButtonDown ? downOverlay | |||||
| : (isMouseOverButton ? overOverlay | |||||
| : normalOverlay), | |||||
| isButtonDown ? downOpacity | |||||
| : (isMouseOverButton ? overOpacity | |||||
| : normalOpacity), | |||||
| *this); | |||||
| } | |||||
| } | |||||
| bool ImageButton::hitTest (int x, int y) | |||||
| { | |||||
| if (alphaThreshold == 0) | |||||
| return true; | |||||
| Image* const im = getCurrentImage(); | |||||
| return im == 0 | |||||
| || (imageW > 0 && imageH > 0 | |||||
| && alphaThreshold < im->getPixelAt (((x - imageX) * im->getWidth()) / imageW, | |||||
| ((y - imageY) * im->getHeight()) / imageH).getAlpha()); | |||||
| } | |||||
| END_JUCE_NAMESPACE | |||||
| @@ -803,6 +803,7 @@ TreeViewItem::TreeViewItem() | |||||
| selected (false), | selected (false), | ||||
| redrawNeeded (true), | redrawNeeded (true), | ||||
| drawLinesInside (true), | drawLinesInside (true), | ||||
| drawsInLeftMargin (false), | |||||
| openness (opennessDefault) | openness (opennessDefault) | ||||
| { | { | ||||
| static int nextUID = 0; | static int nextUID = 0; | ||||
| @@ -1077,6 +1078,11 @@ int TreeViewItem::getIndentX() const throw() | |||||
| return x; | return x; | ||||
| } | } | ||||
| void TreeViewItem::setDrawsInLeftMargin (bool canDrawInLeftMargin) throw() | |||||
| { | |||||
| drawsInLeftMargin = canDrawInLeftMargin; | |||||
| } | |||||
| void TreeViewItem::paintRecursively (Graphics& g, int width) | void TreeViewItem::paintRecursively (Graphics& g, int width) | ||||
| { | { | ||||
| jassert (ownerView != 0); | jassert (ownerView != 0); | ||||
| @@ -1152,7 +1158,8 @@ void TreeViewItem::paintRecursively (Graphics& g, int width) | |||||
| g.saveState(); | g.saveState(); | ||||
| g.setOrigin (indent, 0); | g.setOrigin (indent, 0); | ||||
| if (g.reduceClipRegion (0, 0, itemW, itemHeight)) | |||||
| if (g.reduceClipRegion (drawsInLeftMargin ? -indent : 0, 0, | |||||
| drawsInLeftMargin ? itemW + indent : itemW, itemHeight)) | |||||
| paintItem (g, itemW, itemHeight); | paintItem (g, itemW, itemHeight); | ||||
| g.restoreState(); | g.restoreState(); | ||||
| @@ -345,6 +345,21 @@ public: | |||||
| */ | */ | ||||
| virtual const String getDragSourceDescription(); | virtual const String getDragSourceDescription(); | ||||
| /** Sets a flag to indicate that the item wants to be allowed | |||||
| to draw all the way across to the left edge of the treeview. | |||||
| By default this is false, which means that when the paintItem() | |||||
| method is called, its graphics context is clipped to only allow | |||||
| drawing within the item's rectangle. If this flag is set to true, | |||||
| then the graphics context isn't clipped on its left side, so it | |||||
| can draw all the way across to the left margin. Note that the | |||||
| context will still have its origin in the same place though, so | |||||
| the coordinates of anything to its left will be negative. It's | |||||
| mostly useful if you want to draw a wider bar behind the | |||||
| highlighted item. | |||||
| */ | |||||
| void setDrawsInLeftMargin (bool canDrawInLeftMargin) throw(); | |||||
| //============================================================================== | //============================================================================== | ||||
| juce_UseDebuggingNewOperator | juce_UseDebuggingNewOperator | ||||
| @@ -357,6 +372,7 @@ private: | |||||
| bool selected : 1; | bool selected : 1; | ||||
| bool redrawNeeded : 1; | bool redrawNeeded : 1; | ||||
| bool drawLinesInside : 1; | bool drawLinesInside : 1; | ||||
| bool drawsInLeftMargin : 1; | |||||
| unsigned int openness : 2; | unsigned int openness : 2; | ||||
| friend class TreeView; | friend class TreeView; | ||||
| @@ -187,6 +187,14 @@ void ComponentBoundsConstrainer::setBoundsForComponent (Component* const compone | |||||
| applyBoundsToComponent (component, x, y, w, h); | applyBoundsToComponent (component, x, y, w, h); | ||||
| } | } | ||||
| void ComponentBoundsConstrainer::checkComponentBounds (Component* component) | |||||
| { | |||||
| setBoundsForComponent (component, | |||||
| component->getX(), component->getY(), | |||||
| component->getWidth(), component->getHeight(), | |||||
| false, false, false, false); | |||||
| } | |||||
| void ComponentBoundsConstrainer::applyBoundsToComponent (Component* component, | void ComponentBoundsConstrainer::applyBoundsToComponent (Component* component, | ||||
| int x, int y, int w, int h) | int x, int y, int w, int h) | ||||
| { | { | ||||
| @@ -172,6 +172,11 @@ public: | |||||
| const bool isStretchingBottom, | const bool isStretchingBottom, | ||||
| const bool isStretchingRight); | const bool isStretchingRight); | ||||
| /** Performs a check on the current size of a component, and moves or resizes | |||||
| it if it fails the constraints. | |||||
| */ | |||||
| void checkComponentBounds (Component* component); | |||||
| /** Called by setBoundsForComponent() to apply a new constrained size to a | /** Called by setBoundsForComponent() to apply a new constrained size to a | ||||
| component. | component. | ||||
| @@ -197,7 +197,7 @@ public: | |||||
| To deselect all the tabs, use an index of -1. | To deselect all the tabs, use an index of -1. | ||||
| */ | */ | ||||
| void setCurrentTabIndex (int newTabIndex); | |||||
| void setCurrentTabIndex (int newTabIndex, const bool sendChangeMessage = true); | |||||
| /** Returns the name of the currently selected tab. | /** Returns the name of the currently selected tab. | ||||
| @@ -216,9 +216,9 @@ void TabbedComponent::setTabBackgroundColour (const int tabIndex, const Colour& | |||||
| repaint(); | repaint(); | ||||
| } | } | ||||
| void TabbedComponent::setCurrentTabIndex (const int newTabIndex) | |||||
| void TabbedComponent::setCurrentTabIndex (const int newTabIndex, const bool sendChangeMessage) | |||||
| { | { | ||||
| tabs->setCurrentTabIndex (newTabIndex); | |||||
| tabs->setCurrentTabIndex (newTabIndex, sendChangeMessage); | |||||
| } | } | ||||
| int TabbedComponent::getCurrentTabIndex() const | int TabbedComponent::getCurrentTabIndex() const | ||||
| @@ -157,7 +157,7 @@ public: | |||||
| @see TabbedButtonBar::setCurrentTabIndex | @see TabbedButtonBar::setCurrentTabIndex | ||||
| */ | */ | ||||
| void setCurrentTabIndex (const int newTabIndex); | |||||
| void setCurrentTabIndex (const int newTabIndex, const bool sendChangeMessage = true); | |||||
| /** Returns the index of the currently selected tab. | /** Returns the index of the currently selected tab. | ||||
| @@ -1626,8 +1626,11 @@ void LookAndFeel::drawImageButton (Graphics& g, Image* image, | |||||
| int imageX, int imageY, int imageW, int imageH, | int imageX, int imageY, int imageW, int imageH, | ||||
| const Colour& overlayColour, | const Colour& overlayColour, | ||||
| float imageOpacity, | float imageOpacity, | ||||
| ImageButton& /*button*/) | |||||
| ImageButton& button) | |||||
| { | { | ||||
| if (! button.isEnabled()) | |||||
| imageOpacity *= 0.3f; | |||||
| if (! overlayColour.isOpaque()) | if (! overlayColour.isOpaque()) | ||||
| { | { | ||||
| g.setOpacity (imageOpacity); | g.setOpacity (imageOpacity); | ||||
| @@ -488,7 +488,8 @@ void Graphics::drawBevel (const int x, | |||||
| const int bevelThickness, | const int bevelThickness, | ||||
| const Colour& topLeftColour, | const Colour& topLeftColour, | ||||
| const Colour& bottomRightColour, | const Colour& bottomRightColour, | ||||
| const bool useGradient) const throw() | |||||
| const bool useGradient, | |||||
| const bool sharpEdgeOnOutside) const throw() | |||||
| { | { | ||||
| // passing in a silly number can cause maths problems in rendering! | // passing in a silly number can cause maths problems in rendering! | ||||
| ASSERT_COORDS_ARE_SENSIBLE_NUMBERS (x, y, width, height); | ASSERT_COORDS_ARE_SENSIBLE_NUMBERS (x, y, width, height); | ||||
| @@ -500,7 +501,7 @@ void Graphics::drawBevel (const int x, | |||||
| for (int i = bevelThickness; --i >= 0;) | for (int i = bevelThickness; --i >= 0;) | ||||
| { | { | ||||
| const float op = useGradient ? ramp * (bevelThickness - i) | |||||
| const float op = useGradient ? ramp * (sharpEdgeOnOutside ? bevelThickness - i : i) | |||||
| : oldOpacity; | : oldOpacity; | ||||
| context->fillRectWithColour (x + i, y + i, width - i * 2, 1, topLeftColour.withMultipliedAlpha (op), false); | context->fillRectWithColour (x + i, y + i, width - i * 2, 1, topLeftColour.withMultipliedAlpha (op), false); | ||||
| @@ -354,6 +354,11 @@ public: | |||||
| The top-left colour is used for the top- and left-hand edges of the | The top-left colour is used for the top- and left-hand edges of the | ||||
| bevel; the bottom-right colour is used for the bottom- and right-hand | bevel; the bottom-right colour is used for the bottom- and right-hand | ||||
| edges. | edges. | ||||
| If useGradient is true, then the bevel fades out to make it look more curved | |||||
| and less angular. If sharpEdgeOnOutside is true, the outside of the bevel is | |||||
| sharp, and it fades towards the centre; if sharpEdgeOnOutside is false, then | |||||
| the centre edges are sharp and it fades towards the outside. | |||||
| */ | */ | ||||
| void drawBevel (const int x, | void drawBevel (const int x, | ||||
| const int y, | const int y, | ||||
| @@ -362,7 +367,8 @@ public: | |||||
| const int bevelThickness, | const int bevelThickness, | ||||
| const Colour& topLeftColour = Colours::white, | const Colour& topLeftColour = Colours::white, | ||||
| const Colour& bottomRightColour = Colours::black, | const Colour& bottomRightColour = Colours::black, | ||||
| const bool useGradient = true) const throw(); | |||||
| const bool useGradient = true, | |||||
| const bool sharpEdgeOnOutside = true) const throw(); | |||||
| /** Draws a pixel using the current colour or brush. | /** Draws a pixel using the current colour or brush. | ||||
| */ | */ | ||||
| @@ -245,14 +245,14 @@ Image* juce_loadJPEGImageFromStream (InputStream& in) throw() | |||||
| } | } | ||||
| jpeg_finish_decompress (&jpegDecompStruct); | jpeg_finish_decompress (&jpegDecompStruct); | ||||
| in.setPosition (((char*) jpegDecompStruct.src->next_input_byte) - (char*) mb.getData()); | |||||
| } | } | ||||
| jpeg_destroy_decompress (&jpegDecompStruct); | jpeg_destroy_decompress (&jpegDecompStruct); | ||||
| } | } | ||||
| catch (...) | catch (...) | ||||
| {} | {} | ||||
| in.setPosition (((char*) jpegDecompStruct.src->next_input_byte) - (char*) mb.getData()); | |||||
| } | } | ||||
| return image; | return image; | ||||
| @@ -301,8 +301,11 @@ public: | |||||
| /** Converts the array to a number string. | /** Converts the array to a number string. | ||||
| Specify a base such as 2 (binary), 8 (octal), 10 (decimal), 16 (hex). | Specify a base such as 2 (binary), 8 (octal), 10 (decimal), 16 (hex). | ||||
| If minuimumNumCharacters is greater than 0, the returned string will be | |||||
| padded with leading zeros to reach at least that length. | |||||
| */ | */ | ||||
| const String toString (const int base) const throw(); | |||||
| const String toString (const int base, const int minimumNumCharacters = 1) const throw(); | |||||
| /** Converts a number string to an array. | /** Converts a number string to an array. | ||||
| @@ -1,144 +1,158 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||||
| Copyright 2004-7 by Raw Material Software ltd. | |||||
| ------------------------------------------------------------------------------ | |||||
| JUCE can be redistributed and/or modified under the terms of the | |||||
| GNU General Public License, as published by the Free Software Foundation; | |||||
| either version 2 of the License, or (at your option) any later version. | |||||
| JUCE is distributed in the hope that it will be useful, | |||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| GNU General Public License for more details. | |||||
| You should have received a copy of the GNU General Public License | |||||
| along with JUCE; if not, visit www.gnu.org/licenses or write to the | |||||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||||
| Boston, MA 02111-1307 USA | |||||
| ------------------------------------------------------------------------------ | |||||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||||
| more information. | |||||
| ============================================================================== | |||||
| */ | |||||
| #include "../basics/juce_StandardHeader.h" | |||||
| BEGIN_JUCE_NAMESPACE | |||||
| #include "juce_StringPairArray.h" | |||||
| //============================================================================== | |||||
| StringPairArray::StringPairArray (const bool ignoreCase_) throw() | |||||
| : ignoreCase (ignoreCase_) | |||||
| { | |||||
| } | |||||
| StringPairArray::StringPairArray (const StringPairArray& other) throw() | |||||
| : keys (other.keys), | |||||
| values (other.values), | |||||
| ignoreCase (other.ignoreCase) | |||||
| { | |||||
| } | |||||
| StringPairArray::~StringPairArray() throw() | |||||
| { | |||||
| } | |||||
| const StringPairArray& StringPairArray::operator= (const StringPairArray& other) throw() | |||||
| { | |||||
| keys = other.keys; | |||||
| values = other.values; | |||||
| return *this; | |||||
| } | |||||
| bool StringPairArray::operator== (const StringPairArray& other) const throw() | |||||
| { | |||||
| for (int i = keys.size(); --i >= 0;) | |||||
| if (other [keys[i]] != values[i]) | |||||
| return false; | |||||
| return true; | |||||
| } | |||||
| bool StringPairArray::operator!= (const StringPairArray& other) const throw() | |||||
| { | |||||
| return ! operator== (other); | |||||
| } | |||||
| const String& StringPairArray::operator[] (const String& key) const throw() | |||||
| { | |||||
| return values [keys.indexOf (key, ignoreCase)]; | |||||
| } | |||||
| const String StringPairArray::getValue (const String& key, const String& defaultReturnValue) const | |||||
| { | |||||
| const int i = keys.indexOf (key, ignoreCase); | |||||
| if (i >= 0) | |||||
| return values[i]; | |||||
| return defaultReturnValue; | |||||
| } | |||||
| void StringPairArray::set (const String& key, | |||||
| const String& value) throw() | |||||
| { | |||||
| const int i = keys.indexOf (key, ignoreCase); | |||||
| if (i >= 0) | |||||
| { | |||||
| values.set (i, value); | |||||
| } | |||||
| else | |||||
| { | |||||
| keys.add (key); | |||||
| values.add (value); | |||||
| } | |||||
| } | |||||
| void StringPairArray::addArray (const StringPairArray& other) | |||||
| { | |||||
| for (int i = 0; i < other.size(); ++i) | |||||
| set (other.keys[i], other.values[i]); | |||||
| } | |||||
| void StringPairArray::clear() throw() | |||||
| { | |||||
| keys.clear(); | |||||
| values.clear(); | |||||
| } | |||||
| void StringPairArray::remove (const String& key) throw() | |||||
| { | |||||
| remove (keys.indexOf (key, ignoreCase)); | |||||
| } | |||||
| void StringPairArray::remove (const int index) throw() | |||||
| { | |||||
| keys.remove (index); | |||||
| values.remove (index); | |||||
| } | |||||
| void StringPairArray::setIgnoresCase (const bool shouldIgnoreCase) throw() | |||||
| { | |||||
| ignoreCase = shouldIgnoreCase; | |||||
| } | |||||
| void StringPairArray::minimiseStorageOverheads() throw() | |||||
| { | |||||
| keys.minimiseStorageOverheads(); | |||||
| values.minimiseStorageOverheads(); | |||||
| } | |||||
| END_JUCE_NAMESPACE | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||||
| Copyright 2004-7 by Raw Material Software ltd. | |||||
| ------------------------------------------------------------------------------ | |||||
| JUCE can be redistributed and/or modified under the terms of the | |||||
| GNU General Public License, as published by the Free Software Foundation; | |||||
| either version 2 of the License, or (at your option) any later version. | |||||
| JUCE is distributed in the hope that it will be useful, | |||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| GNU General Public License for more details. | |||||
| You should have received a copy of the GNU General Public License | |||||
| along with JUCE; if not, visit www.gnu.org/licenses or write to the | |||||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||||
| Boston, MA 02111-1307 USA | |||||
| ------------------------------------------------------------------------------ | |||||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||||
| more information. | |||||
| ============================================================================== | |||||
| */ | |||||
| #include "../basics/juce_StandardHeader.h" | |||||
| BEGIN_JUCE_NAMESPACE | |||||
| #include "juce_StringPairArray.h" | |||||
| //============================================================================== | |||||
| StringPairArray::StringPairArray (const bool ignoreCase_) throw() | |||||
| : ignoreCase (ignoreCase_) | |||||
| { | |||||
| } | |||||
| StringPairArray::StringPairArray (const StringPairArray& other) throw() | |||||
| : keys (other.keys), | |||||
| values (other.values), | |||||
| ignoreCase (other.ignoreCase) | |||||
| { | |||||
| } | |||||
| StringPairArray::~StringPairArray() throw() | |||||
| { | |||||
| } | |||||
| const StringPairArray& StringPairArray::operator= (const StringPairArray& other) throw() | |||||
| { | |||||
| keys = other.keys; | |||||
| values = other.values; | |||||
| return *this; | |||||
| } | |||||
| bool StringPairArray::operator== (const StringPairArray& other) const throw() | |||||
| { | |||||
| for (int i = keys.size(); --i >= 0;) | |||||
| if (other [keys[i]] != values[i]) | |||||
| return false; | |||||
| return true; | |||||
| } | |||||
| bool StringPairArray::operator!= (const StringPairArray& other) const throw() | |||||
| { | |||||
| return ! operator== (other); | |||||
| } | |||||
| const String& StringPairArray::operator[] (const String& key) const throw() | |||||
| { | |||||
| return values [keys.indexOf (key, ignoreCase)]; | |||||
| } | |||||
| const String StringPairArray::getValue (const String& key, const String& defaultReturnValue) const | |||||
| { | |||||
| const int i = keys.indexOf (key, ignoreCase); | |||||
| if (i >= 0) | |||||
| return values[i]; | |||||
| return defaultReturnValue; | |||||
| } | |||||
| void StringPairArray::set (const String& key, | |||||
| const String& value) throw() | |||||
| { | |||||
| const int i = keys.indexOf (key, ignoreCase); | |||||
| if (i >= 0) | |||||
| { | |||||
| values.set (i, value); | |||||
| } | |||||
| else | |||||
| { | |||||
| keys.add (key); | |||||
| values.add (value); | |||||
| } | |||||
| } | |||||
| void StringPairArray::addArray (const StringPairArray& other) | |||||
| { | |||||
| for (int i = 0; i < other.size(); ++i) | |||||
| set (other.keys[i], other.values[i]); | |||||
| } | |||||
| void StringPairArray::clear() throw() | |||||
| { | |||||
| keys.clear(); | |||||
| values.clear(); | |||||
| } | |||||
| void StringPairArray::remove (const String& key) throw() | |||||
| { | |||||
| remove (keys.indexOf (key, ignoreCase)); | |||||
| } | |||||
| void StringPairArray::remove (const int index) throw() | |||||
| { | |||||
| keys.remove (index); | |||||
| values.remove (index); | |||||
| } | |||||
| void StringPairArray::setIgnoresCase (const bool shouldIgnoreCase) throw() | |||||
| { | |||||
| ignoreCase = shouldIgnoreCase; | |||||
| } | |||||
| const String StringPairArray::getDescription() const | |||||
| { | |||||
| String s; | |||||
| for (int i = 0; i < keys.size(); ++i) | |||||
| { | |||||
| s << keys[i] << T(" = ") << values[i]; | |||||
| if (i < keys.size()) | |||||
| s << T(", "); | |||||
| } | |||||
| return s; | |||||
| } | |||||
| void StringPairArray::minimiseStorageOverheads() throw() | |||||
| { | |||||
| keys.minimiseStorageOverheads(); | |||||
| values.minimiseStorageOverheads(); | |||||
| } | |||||
| END_JUCE_NAMESPACE | |||||
| @@ -143,6 +143,13 @@ public: | |||||
| */ | */ | ||||
| void setIgnoresCase (const bool shouldIgnoreCase) throw(); | void setIgnoresCase (const bool shouldIgnoreCase) throw(); | ||||
| //============================================================================== | |||||
| /** Returns a descriptive string containing the items. | |||||
| This is handy for dumping the contents of an array. | |||||
| */ | |||||
| const String getDescription() const; | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Reduces the amount of storage being used by the array. | /** Reduces the amount of storage being used by the array. | ||||