| @@ -52,6 +52,8 @@ void PlatformUtilities::beep() | |||
| } | |||
| //============================================================================== | |||
| #if ! JUCE_ONLY_BUILD_CORE_LIBRARY | |||
| bool AlertWindow::showNativeDialogBox (const String& title, | |||
| const String& bodyText, | |||
| bool isOkCancel) | |||
| @@ -242,3 +244,6 @@ void juce_updateMultiMonitorInfo (Array <Rectangle>& monitorCoords, const bool c | |||
| } | |||
| #endif | |||
| #endif | |||
| @@ -67,6 +67,8 @@ | |||
| #if MACOS_10_4_OR_EARLIER | |||
| #include <GLUT/glut.h> | |||
| typedef int NSInteger; | |||
| typedef unsigned int NSUInteger; | |||
| #endif | |||
| #endif // __JUCE_MAC_NATIVEINCLUDES_JUCEHEADER__ | |||
| @@ -59,6 +59,9 @@ bool QuickTimeMovieComponent::isQuickTimeAvailable() throw() | |||
| 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; | |||
| 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() | |||
| { | |||
| [[NSPasteboard generalPasteboard] declareTypes: [NSArray arrayWithObject: NSStringPboardType] | |||
| @@ -182,5 +184,6 @@ const String SystemClipboard::getTextFromClipboard() throw() | |||
| : nsStringToJuce (text); | |||
| } | |||
| #endif | |||
| #endif | |||
| @@ -224,12 +224,10 @@ bool juce_canWriteToFile (const String& fileName) throw() | |||
| bool juce_deleteFile (const String& fileName) throw() | |||
| { | |||
| const char* const fileNameUTF8 = fileName.toUTF8(); | |||
| if (juce_isDirectory (fileName)) | |||
| return rmdir (fileNameUTF8) == 0; | |||
| return rmdir ((const char*) fileName.toUTF8()) == 0; | |||
| else | |||
| return remove (fileNameUTF8) == 0; | |||
| return remove ((const char*) fileName.toUTF8()) == 0; | |||
| } | |||
| 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() | |||
| { | |||
| const char* const fileNameUTF8 = fileName.toUTF8(); | |||
| int flags = O_RDONLY; | |||
| if (forWriting) | |||
| { | |||
| 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) | |||
| 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() | |||
| @@ -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" | |||
| 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 | |||
| "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 | |||
| 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) | |||
| { | |||
| JucerComponentHandler::setJucerComponentFile (*layout.getDocument(), newOne, f.getFullPathName()); | |||
| JucerComponentHandler::setJucerComponentFile (*layout.getDocument(), newOne, f.getRelativePathFrom (document.getFile().getParentDirectory())); | |||
| layout.getSelectedSet().selectOnly (newOne); | |||
| } | |||
| @@ -612,6 +612,8 @@ | |||
| #if MACOS_10_4_OR_EARLIER | |||
| #include <GLUT/glut.h> | |||
| typedef int NSInteger; | |||
| typedef unsigned int NSUInteger; | |||
| #endif | |||
| #endif // __JUCE_MAC_NATIVEINCLUDES_JUCEHEADER__ | |||
| @@ -630,7 +632,7 @@ | |||
| #pragma warning (disable: 4309 4305) | |||
| #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 | |||
| /********* 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; | |||
| BitArray v (*this); | |||
| @@ -2821,8 +2823,10 @@ const String BitArray::toString (const int base) const throw() | |||
| 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; | |||
| } | |||
| @@ -12606,6 +12610,20 @@ 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(); | |||
| @@ -19415,8 +19433,6 @@ public: | |||
| #ifdef WIN32 | |||
| if (InitializeQTML (0) != noErr) | |||
| return; | |||
| #elif JUCE_MAC | |||
| EnterMoviesOnThread (0); | |||
| #endif | |||
| if (EnterMovies() != noErr) | |||
| return; | |||
| @@ -42497,7 +42513,7 @@ void ImageButton::setImages (const bool resizeButtonNowToFitThisImage, | |||
| Image* ImageButton::getCurrentImage() const | |||
| { | |||
| if (isDown()) | |||
| if (isDown() || getToggleState()) | |||
| return getDownImage(); | |||
| if (isOver()) | |||
| @@ -45312,7 +45328,7 @@ double Slider::getMaxValue() const throw() | |||
| 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. | |||
| jassert (style == TwoValueHorizontal || style == TwoValueVertical | |||
| @@ -45321,9 +45337,19 @@ void Slider::setMinValue (double newValue, const bool sendUpdateMessage, const b | |||
| newValue = constrainedValue (newValue); | |||
| if (style == TwoValueHorizontal || style == TwoValueVertical) | |||
| { | |||
| if (allowNudgingOfOtherValues && newValue > valueMax) | |||
| setMaxValue (newValue, sendUpdateMessage, sendMessageSynchronously); | |||
| newValue = jmin (valueMax, newValue); | |||
| } | |||
| else | |||
| { | |||
| if (allowNudgingOfOtherValues && newValue > currentValue) | |||
| setValue (newValue, sendUpdateMessage, sendMessageSynchronously); | |||
| newValue = jmin (currentValue, 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. | |||
| jassert (style == TwoValueHorizontal || style == TwoValueVertical | |||
| @@ -45350,9 +45376,19 @@ void Slider::setMaxValue (double newValue, const bool sendUpdateMessage, const b | |||
| newValue = constrainedValue (newValue); | |||
| if (style == TwoValueHorizontal || style == TwoValueVertical) | |||
| { | |||
| if (allowNudgingOfOtherValues && newValue < valueMin) | |||
| setMinValue (newValue, sendUpdateMessage, sendMessageSynchronously); | |||
| newValue = jmax (valueMin, newValue); | |||
| } | |||
| else | |||
| { | |||
| if (allowNudgingOfOtherValues && newValue < currentValue) | |||
| setValue (newValue, sendUpdateMessage, sendMessageSynchronously); | |||
| newValue = jmax (currentValue, newValue); | |||
| } | |||
| if (valueMax != newValue) | |||
| { | |||
| @@ -45748,6 +45784,10 @@ void Slider::mouseDown (const MouseEvent& e) | |||
| { | |||
| mouseWasHidden = false; | |||
| incDecDragged = false; | |||
| mouseXWhenLastDragged = e.x; | |||
| mouseYWhenLastDragged = e.y; | |||
| mouseDragStartX = e.getMouseDownX(); | |||
| mouseDragStartY = e.getMouseDownY(); | |||
| if (isEnabled()) | |||
| { | |||
| @@ -45826,8 +45866,6 @@ void Slider::mouseDown (const MouseEvent& e) | |||
| minMaxDiff = valueMax - valueMin; | |||
| mouseXWhenLastDragged = e.x; | |||
| mouseYWhenLastDragged = e.y; | |||
| lastAngle = rotaryStart + (rotaryEnd - rotaryStart) | |||
| * valueToProportionOfLength (currentValue); | |||
| @@ -46016,13 +46054,14 @@ void Slider::mouseDrag (const MouseEvent& e) | |||
| && valueBox != 0 && valueBox->isEditable()) | |||
| 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; | |||
| incDecDragged = true; | |||
| mouseDragStartX = e.x; | |||
| mouseDragStartY = e.y; | |||
| } | |||
| 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 == LinearBar | |||
| || (style == IncDecButtons && incDecDragDirectionIsHorizontal())) | |||
| ? e.getDistanceFromDragStartX() | |||
| : -e.getDistanceFromDragStartY(); | |||
| ? e.x - mouseDragStartX | |||
| : mouseDragStartY - e.y; | |||
| double newPos = valueToProportionOfLength (valueOnMouseDown) | |||
| + mouseDiff * (1.0 / pixelsForFullDragExtent); | |||
| @@ -46109,10 +46148,10 @@ void Slider::mouseDrag (const MouseEvent& e) | |||
| else if (sliderBeingDragged == 1) | |||
| { | |||
| setMinValue (snapValue (valueWhenLastDragged, true), | |||
| ! sendChangeOnlyOnRelease, false); | |||
| ! sendChangeOnlyOnRelease, false, true); | |||
| if (e.mods.isShiftDown()) | |||
| setMaxValue (getMinValue() + minMaxDiff, false); | |||
| setMaxValue (getMinValue() + minMaxDiff, false, false, true); | |||
| else | |||
| minMaxDiff = valueMax - valueMin; | |||
| } | |||
| @@ -46121,10 +46160,10 @@ void Slider::mouseDrag (const MouseEvent& e) | |||
| jassert (sliderBeingDragged == 2); | |||
| setMaxValue (snapValue (valueWhenLastDragged, true), | |||
| ! sendChangeOnlyOnRelease, false); | |||
| ! sendChangeOnlyOnRelease, false, true); | |||
| if (e.mods.isShiftDown()) | |||
| setMinValue (getMaxValue() - minMaxDiff, false); | |||
| setMinValue (getMaxValue() - minMaxDiff, false, false, true); | |||
| else | |||
| minMaxDiff = valueMax - valueMin; | |||
| } | |||
| @@ -52151,6 +52190,7 @@ TreeViewItem::TreeViewItem() | |||
| selected (false), | |||
| redrawNeeded (true), | |||
| drawLinesInside (true), | |||
| drawsInLeftMargin (false), | |||
| openness (opennessDefault) | |||
| { | |||
| static int nextUID = 0; | |||
| @@ -52425,6 +52465,11 @@ int TreeViewItem::getIndentX() const throw() | |||
| return x; | |||
| } | |||
| void TreeViewItem::setDrawsInLeftMargin (bool canDrawInLeftMargin) throw() | |||
| { | |||
| drawsInLeftMargin = canDrawInLeftMargin; | |||
| } | |||
| void TreeViewItem::paintRecursively (Graphics& g, int width) | |||
| { | |||
| jassert (ownerView != 0); | |||
| @@ -52499,7 +52544,8 @@ void TreeViewItem::paintRecursively (Graphics& g, int width) | |||
| g.saveState(); | |||
| 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); | |||
| g.restoreState(); | |||
| @@ -56669,6 +56715,14 @@ void ComponentBoundsConstrainer::setBoundsForComponent (Component* const compone | |||
| 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, | |||
| int x, int y, int w, int h) | |||
| { | |||
| @@ -58996,7 +59050,7 @@ const StringArray TabbedButtonBar::getTabNames() const | |||
| return tabs; | |||
| } | |||
| void TabbedButtonBar::setCurrentTabIndex (int newIndex) | |||
| void TabbedButtonBar::setCurrentTabIndex (int newIndex, const bool sendChangeMessage_) | |||
| { | |||
| if (currentTabIndex != newIndex) | |||
| { | |||
| @@ -59014,7 +59068,9 @@ void TabbedButtonBar::setCurrentTabIndex (int newIndex) | |||
| } | |||
| resized(); | |||
| sendChangeMessage (this); | |||
| if (sendChangeMessage_) | |||
| sendChangeMessage (this); | |||
| currentTabChanged (newIndex, newIndex >= 0 ? tabs [newIndex] : String::empty); | |||
| } | |||
| @@ -59396,9 +59452,9 @@ void TabbedComponent::setTabBackgroundColour (const int tabIndex, const Colour& | |||
| 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 | |||
| @@ -61369,8 +61425,11 @@ void LookAndFeel::drawImageButton (Graphics& g, Image* image, | |||
| int imageX, int imageY, int imageW, int imageH, | |||
| const Colour& overlayColour, | |||
| float imageOpacity, | |||
| ImageButton& /*button*/) | |||
| ImageButton& button) | |||
| { | |||
| if (! button.isEnabled()) | |||
| imageOpacity *= 0.3f; | |||
| if (! overlayColour.isOpaque()) | |||
| { | |||
| g.setOpacity (imageOpacity); | |||
| @@ -71847,6 +71906,8 @@ ComponentPeer::~ComponentPeer() | |||
| { | |||
| heavyweightPeers.removeValue (this); | |||
| delete dragAndDropTargetComponent; | |||
| Desktop::getInstance().triggerFocusCallback(); | |||
| } | |||
| int ComponentPeer::getNumPeers() throw() | |||
| @@ -76119,7 +76180,8 @@ void Graphics::drawBevel (const int x, | |||
| const int bevelThickness, | |||
| const Colour& topLeftColour, | |||
| 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! | |||
| 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;) | |||
| { | |||
| const float op = useGradient ? ramp * (bevelThickness - i) | |||
| const float op = useGradient ? ramp * (sharpEdgeOnOutside ? bevelThickness - i : i) | |||
| : oldOpacity; | |||
| 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); | |||
| in.setPosition (((char*) jpegDecompStruct.src->next_input_byte) - (char*) mb.getData()); | |||
| } | |||
| jpeg_destroy_decompress (&jpegDecompStruct); | |||
| } | |||
| catch (...) | |||
| {} | |||
| in.setPosition (((char*) jpegDecompStruct.src->next_input_byte) - (char*) mb.getData()); | |||
| } | |||
| return image; | |||
| @@ -254840,12 +254902,10 @@ bool juce_canWriteToFile (const String& fileName) throw() | |||
| bool juce_deleteFile (const String& fileName) throw() | |||
| { | |||
| const char* const fileNameUTF8 = fileName.toUTF8(); | |||
| if (juce_isDirectory (fileName)) | |||
| return rmdir (fileNameUTF8) == 0; | |||
| return rmdir ((const char*) fileName.toUTF8()) == 0; | |||
| else | |||
| return remove (fileNameUTF8) == 0; | |||
| return remove ((const char*) fileName.toUTF8()) == 0; | |||
| } | |||
| 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() | |||
| { | |||
| const char* const fileNameUTF8 = fileName.toUTF8(); | |||
| int flags = O_RDONLY; | |||
| if (forWriting) | |||
| { | |||
| 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) | |||
| 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() | |||
| @@ -263836,6 +263895,8 @@ const String PlatformUtilities::convertToPrecomposedUnicode (const String& s) | |||
| return result; | |||
| } | |||
| #if ! JUCE_ONLY_BUILD_CORE_LIBRARY | |||
| void SystemClipboard::copyTextToClipboard (const String& text) throw() | |||
| { | |||
| [[NSPasteboard generalPasteboard] declareTypes: [NSArray arrayWithObject: NSStringPboardType] | |||
| @@ -263853,6 +263914,8 @@ const String SystemClipboard::getTextFromClipboard() throw() | |||
| : nsStringToJuce (text); | |||
| } | |||
| #endif | |||
| #endif | |||
| /********* 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() | |||
| { | |||
| const char* const fileNameUTF8 = fileName.toUTF8(); | |||
| if (juce_isDirectory (fileName)) | |||
| return rmdir (fileNameUTF8) == 0; | |||
| return rmdir ((const char*) fileName.toUTF8()) == 0; | |||
| else | |||
| return remove (fileNameUTF8) == 0; | |||
| return remove ((const char*) fileName.toUTF8()) == 0; | |||
| } | |||
| 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() | |||
| { | |||
| const char* const fileNameUTF8 = fileName.toUTF8(); | |||
| int flags = O_RDONLY; | |||
| if (forWriting) | |||
| { | |||
| 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) | |||
| 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() | |||
| @@ -265665,6 +265725,8 @@ void PlatformUtilities::beep() | |||
| NSBeep(); | |||
| } | |||
| #if ! JUCE_ONLY_BUILD_CORE_LIBRARY | |||
| bool AlertWindow::showNativeDialogBox (const String& title, | |||
| const String& bodyText, | |||
| bool isOkCancel) | |||
| @@ -265851,6 +265913,9 @@ void juce_updateMultiMonitorInfo (Array <Rectangle>& monitorCoords, const bool c | |||
| } | |||
| #endif | |||
| #endif | |||
| /********* End of inlined file: juce_mac_MiscUtilities.mm *********/ | |||
| /********* Start of inlined file: juce_mac_Debugging.mm *********/ | |||
| @@ -268784,6 +268849,9 @@ bool QuickTimeMovieComponent::isQuickTimeAvailable() throw() | |||
| 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; | |||
| FileInputStream* const fin = dynamic_cast <FileInputStream*> (movieStream); | |||
| @@ -7309,8 +7309,11 @@ public: | |||
| /** Converts the array to a number string. | |||
| 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. | |||
| @@ -8107,6 +8110,12 @@ public: | |||
| */ | |||
| 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. | |||
| 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 | |||
| bevel; the bottom-right colour is used for the bottom- and right-hand | |||
| 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, | |||
| const int y, | |||
| @@ -19590,7 +19604,8 @@ public: | |||
| const int bevelThickness, | |||
| const Colour& topLeftColour = Colours::white, | |||
| 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. | |||
| */ | |||
| @@ -37968,7 +37983,7 @@ public: | |||
| { | |||
| MessageManagerLock mml (Thread::getCurrentThread()); | |||
| if (! mml.lockWasGained) | |||
| if (! mml.lockWasGained()) | |||
| return; // another thread is trying to kill us! | |||
| ..do some locked stuff here.. | |||
| @@ -43250,6 +43265,21 @@ public: | |||
| */ | |||
| 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 | |||
| private: | |||
| @@ -43261,6 +43291,7 @@ private: | |||
| bool selected : 1; | |||
| bool redrawNeeded : 1; | |||
| bool drawLinesInside : 1; | |||
| bool drawsInLeftMargin : 1; | |||
| unsigned int openness : 2; | |||
| friend class TreeView; | |||
| @@ -44025,6 +44056,11 @@ public: | |||
| const bool isStretchingBottom, | |||
| 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 | |||
| component. | |||
| @@ -45311,18 +45347,22 @@ public: | |||
| want to handle it. | |||
| @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 | |||
| any SliderListeners or the valueChanged() method | |||
| @param sendMessageSynchronously if true, then a call to the SliderListeners will be made | |||
| 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 | |||
| */ | |||
| void setMinValue (double newValue, | |||
| 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. | |||
| @@ -45341,18 +45381,22 @@ public: | |||
| want to handle it. | |||
| @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 | |||
| any SliderListeners or the valueChanged() method | |||
| @param sendMessageSynchronously if true, then a call to the SliderListeners will be made | |||
| 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 | |||
| */ | |||
| void setMaxValue (double newValue, | |||
| 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. */ | |||
| void addListener (SliderListener* const listener) throw(); | |||
| @@ -45625,6 +45669,7 @@ private: | |||
| int velocityModeThreshold; | |||
| float rotaryStart, rotaryEnd; | |||
| int numDecimalPlaces, mouseXWhenLastDragged, mouseYWhenLastDragged; | |||
| int mouseDragStartX, mouseDragStartY; | |||
| int sliderRegionStart, sliderRegionSize; | |||
| int sliderBeingDragged; | |||
| int pixelsForFullDragExtent; | |||
| @@ -47134,7 +47179,7 @@ public: | |||
| 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. | |||
| @@ -47353,7 +47398,7 @@ public: | |||
| @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. | |||
| @@ -66,7 +66,7 @@ | |||
| #pragma warning (disable: 4309 4305) | |||
| #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 | |||
| #include "../build/macosx/platform_specific_code/juce_mac_CarbonViewWrapperComponent.h" | |||
| END_JUCE_NAMESPACE | |||
| @@ -97,8 +97,6 @@ public: | |||
| #ifdef WIN32 | |||
| if (InitializeQTML (0) != noErr) | |||
| return; | |||
| #elif JUCE_MAC | |||
| EnterMoviesOnThread (0); | |||
| #endif | |||
| if (EnterMovies() != noErr) | |||
| return; | |||
| @@ -279,7 +279,7 @@ public: | |||
| { | |||
| MessageManagerLock mml (Thread::getCurrentThread()); | |||
| if (! mml.lockWasGained) | |||
| if (! mml.lockWasGained()) | |||
| return; // another thread is trying to kill us! | |||
| ..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), | |||
| redrawNeeded (true), | |||
| drawLinesInside (true), | |||
| drawsInLeftMargin (false), | |||
| openness (opennessDefault) | |||
| { | |||
| static int nextUID = 0; | |||
| @@ -1077,6 +1078,11 @@ int TreeViewItem::getIndentX() const throw() | |||
| return x; | |||
| } | |||
| void TreeViewItem::setDrawsInLeftMargin (bool canDrawInLeftMargin) throw() | |||
| { | |||
| drawsInLeftMargin = canDrawInLeftMargin; | |||
| } | |||
| void TreeViewItem::paintRecursively (Graphics& g, int width) | |||
| { | |||
| jassert (ownerView != 0); | |||
| @@ -1152,7 +1158,8 @@ void TreeViewItem::paintRecursively (Graphics& g, int width) | |||
| g.saveState(); | |||
| 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); | |||
| g.restoreState(); | |||
| @@ -345,6 +345,21 @@ public: | |||
| */ | |||
| 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 | |||
| @@ -357,6 +372,7 @@ private: | |||
| bool selected : 1; | |||
| bool redrawNeeded : 1; | |||
| bool drawLinesInside : 1; | |||
| bool drawsInLeftMargin : 1; | |||
| unsigned int openness : 2; | |||
| friend class TreeView; | |||
| @@ -187,6 +187,14 @@ void ComponentBoundsConstrainer::setBoundsForComponent (Component* const compone | |||
| 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, | |||
| int x, int y, int w, int h) | |||
| { | |||
| @@ -172,6 +172,11 @@ public: | |||
| const bool isStretchingBottom, | |||
| 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 | |||
| component. | |||
| @@ -197,7 +197,7 @@ public: | |||
| 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. | |||
| @@ -216,9 +216,9 @@ void TabbedComponent::setTabBackgroundColour (const int tabIndex, const Colour& | |||
| 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 | |||
| @@ -157,7 +157,7 @@ public: | |||
| @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. | |||
| @@ -1626,8 +1626,11 @@ void LookAndFeel::drawImageButton (Graphics& g, Image* image, | |||
| int imageX, int imageY, int imageW, int imageH, | |||
| const Colour& overlayColour, | |||
| float imageOpacity, | |||
| ImageButton& /*button*/) | |||
| ImageButton& button) | |||
| { | |||
| if (! button.isEnabled()) | |||
| imageOpacity *= 0.3f; | |||
| if (! overlayColour.isOpaque()) | |||
| { | |||
| g.setOpacity (imageOpacity); | |||
| @@ -488,7 +488,8 @@ void Graphics::drawBevel (const int x, | |||
| const int bevelThickness, | |||
| const Colour& topLeftColour, | |||
| 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! | |||
| 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;) | |||
| { | |||
| const float op = useGradient ? ramp * (bevelThickness - i) | |||
| const float op = useGradient ? ramp * (sharpEdgeOnOutside ? bevelThickness - i : i) | |||
| : oldOpacity; | |||
| 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 | |||
| bevel; the bottom-right colour is used for the bottom- and right-hand | |||
| 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, | |||
| const int y, | |||
| @@ -362,7 +367,8 @@ public: | |||
| const int bevelThickness, | |||
| const Colour& topLeftColour = Colours::white, | |||
| 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. | |||
| */ | |||
| @@ -245,14 +245,14 @@ Image* juce_loadJPEGImageFromStream (InputStream& in) throw() | |||
| } | |||
| jpeg_finish_decompress (&jpegDecompStruct); | |||
| in.setPosition (((char*) jpegDecompStruct.src->next_input_byte) - (char*) mb.getData()); | |||
| } | |||
| jpeg_destroy_decompress (&jpegDecompStruct); | |||
| } | |||
| catch (...) | |||
| {} | |||
| in.setPosition (((char*) jpegDecompStruct.src->next_input_byte) - (char*) mb.getData()); | |||
| } | |||
| return image; | |||
| @@ -301,8 +301,11 @@ public: | |||
| /** Converts the array to a number string. | |||
| 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. | |||
| @@ -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(); | |||
| //============================================================================== | |||
| /** 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. | |||