diff --git a/Builds/Linux/Makefile b/Builds/Linux/Makefile index 1904f94134..e5f1551fb2 100644 --- a/Builds/Linux/Makefile +++ b/Builds/Linux/Makefile @@ -249,7 +249,6 @@ OBJECTS := \ $(OBJDIR)/juce_SVGParser_b79416c5.o \ $(OBJDIR)/juce_DropShadowEffect_da52d75.o \ $(OBJDIR)/juce_GlowEffect_c0959893.o \ - $(OBJDIR)/juce_ReduceOpacityEffect_e8e7a60b.o \ $(OBJDIR)/juce_Font_fa88db26.o \ $(OBJDIR)/juce_GlyphArrangement_f0797295.o \ $(OBJDIR)/juce_TextLayout_d18f700e.o \ @@ -1414,11 +1413,6 @@ $(OBJDIR)/juce_GlowEffect_c0959893.o: ../../src/gui/graphics/effects/juce_GlowEf @echo "Compiling juce_GlowEffect.cpp" @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" -$(OBJDIR)/juce_ReduceOpacityEffect_e8e7a60b.o: ../../src/gui/graphics/effects/juce_ReduceOpacityEffect.cpp - -@mkdir -p $(OBJDIR) - @echo "Compiling juce_ReduceOpacityEffect.cpp" - @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" - $(OBJDIR)/juce_Font_fa88db26.o: ../../src/gui/graphics/fonts/juce_Font.cpp -@mkdir -p $(OBJDIR) @echo "Compiling juce_Font.cpp" diff --git a/Builds/MacOSX/Juce.xcodeproj/project.pbxproj b/Builds/MacOSX/Juce.xcodeproj/project.pbxproj index dd4191b63d..ca9f2ff5a4 100644 --- a/Builds/MacOSX/Juce.xcodeproj/project.pbxproj +++ b/Builds/MacOSX/Juce.xcodeproj/project.pbxproj @@ -218,7 +218,6 @@ 645AF66C048A4815F5A8ECDD = { isa = PBXBuildFile; fileRef = 2BFC199D03DEEC329D6A7CB1; }; 38EFE824E76B3BB99824C265 = { isa = PBXBuildFile; fileRef = 32EA297812F1C88B42099501; }; E23C5C51305DC7CE30E4DAB7 = { isa = PBXBuildFile; fileRef = CB649686575473223C859482; }; - 89C96A721F3B54CF3F33848C = { isa = PBXBuildFile; fileRef = 7EBBC368FA350F786EF446B7; }; B92F53BABB6A9AC8348B001E = { isa = PBXBuildFile; fileRef = 78068AA59A5DCFCCAAEA79D0; }; EBC3AA015D24C62FA0307F51 = { isa = PBXBuildFile; fileRef = 61D06B694603F608CDA0703B; }; 803FFCA3DAC0C004A80143B4 = { isa = PBXBuildFile; fileRef = 91CB423DBC5F3CBEDD9CF2EF; }; @@ -834,8 +833,6 @@ CB649686575473223C859482 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_GlowEffect.cpp; path = ../../src/gui/graphics/effects/juce_GlowEffect.cpp; sourceTree = SOURCE_ROOT; }; FD1FA4ABB4226372235643E4 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_GlowEffect.h; path = ../../src/gui/graphics/effects/juce_GlowEffect.h; sourceTree = SOURCE_ROOT; }; 18DB9BD10F140F132A3279C3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ImageEffectFilter.h; path = ../../src/gui/graphics/effects/juce_ImageEffectFilter.h; sourceTree = SOURCE_ROOT; }; - 7EBBC368FA350F786EF446B7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_ReduceOpacityEffect.cpp; path = ../../src/gui/graphics/effects/juce_ReduceOpacityEffect.cpp; sourceTree = SOURCE_ROOT; }; - 8D18743ECC1BF12381811FD6 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ReduceOpacityEffect.h; path = ../../src/gui/graphics/effects/juce_ReduceOpacityEffect.h; sourceTree = SOURCE_ROOT; }; 78068AA59A5DCFCCAAEA79D0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_Font.cpp; path = ../../src/gui/graphics/fonts/juce_Font.cpp; sourceTree = SOURCE_ROOT; }; 0401EA0E883CCAAAC6960A27 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_Font.h; path = ../../src/gui/graphics/fonts/juce_Font.h; sourceTree = SOURCE_ROOT; }; 61D06B694603F608CDA0703B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_GlyphArrangement.cpp; path = ../../src/gui/graphics/fonts/juce_GlyphArrangement.cpp; sourceTree = SOURCE_ROOT; }; @@ -1592,9 +1589,7 @@ 85D4043F9E25047E07496DAC, CB649686575473223C859482, FD1FA4ABB4226372235643E4, - 18DB9BD10F140F132A3279C3, - 7EBBC368FA350F786EF446B7, - 8D18743ECC1BF12381811FD6 ); name = effects; sourceTree = ""; }; + 18DB9BD10F140F132A3279C3 ); name = effects; sourceTree = ""; }; 58FE42C578BFFD1F8F545B39 = { isa = PBXGroup; children = ( 78068AA59A5DCFCCAAEA79D0, 0401EA0E883CCAAAC6960A27, @@ -2143,7 +2138,6 @@ 645AF66C048A4815F5A8ECDD, 38EFE824E76B3BB99824C265, E23C5C51305DC7CE30E4DAB7, - 89C96A721F3B54CF3F33848C, B92F53BABB6A9AC8348B001E, EBC3AA015D24C62FA0307F51, 803FFCA3DAC0C004A80143B4, diff --git a/Builds/VisualStudio2005/Juce.vcproj b/Builds/VisualStudio2005/Juce.vcproj index 7b88684445..91309b0806 100644 --- a/Builds/VisualStudio2005/Juce.vcproj +++ b/Builds/VisualStudio2005/Juce.vcproj @@ -737,8 +737,6 @@ - - diff --git a/Builds/VisualStudio2008/Juce.vcproj b/Builds/VisualStudio2008/Juce.vcproj index 334d3ddc7d..93b63483cc 100644 --- a/Builds/VisualStudio2008/Juce.vcproj +++ b/Builds/VisualStudio2008/Juce.vcproj @@ -737,8 +737,6 @@ - - diff --git a/Builds/VisualStudio2008_DLL/Juce.vcproj b/Builds/VisualStudio2008_DLL/Juce.vcproj index 55231b21f9..af91502958 100644 --- a/Builds/VisualStudio2008_DLL/Juce.vcproj +++ b/Builds/VisualStudio2008_DLL/Juce.vcproj @@ -739,8 +739,6 @@ - - diff --git a/Builds/VisualStudio2010/Juce.vcxproj b/Builds/VisualStudio2010/Juce.vcxproj index 222f58c788..d476cf4950 100644 --- a/Builds/VisualStudio2010/Juce.vcxproj +++ b/Builds/VisualStudio2010/Juce.vcxproj @@ -332,7 +332,6 @@ - @@ -700,7 +699,6 @@ - diff --git a/Builds/VisualStudio2010/Juce.vcxproj.filters b/Builds/VisualStudio2010/Juce.vcxproj.filters index 4a9ad74e3c..36bd373e9b 100644 --- a/Builds/VisualStudio2010/Juce.vcxproj.filters +++ b/Builds/VisualStudio2010/Juce.vcxproj.filters @@ -844,9 +844,6 @@ Juce\Source\gui\graphics\effects - - Juce\Source\gui\graphics\effects - Juce\Source\gui\graphics\fonts @@ -2022,9 +2019,6 @@ Juce\Source\gui\graphics\effects - - Juce\Source\gui\graphics\effects - Juce\Source\gui\graphics\fonts diff --git a/Builds/iPhone/Juce.xcodeproj/project.pbxproj b/Builds/iPhone/Juce.xcodeproj/project.pbxproj index 4dc698cd98..bfdbdbafaf 100644 --- a/Builds/iPhone/Juce.xcodeproj/project.pbxproj +++ b/Builds/iPhone/Juce.xcodeproj/project.pbxproj @@ -218,7 +218,6 @@ 645AF66C048A4815F5A8ECDD = { isa = PBXBuildFile; fileRef = 2BFC199D03DEEC329D6A7CB1; }; 38EFE824E76B3BB99824C265 = { isa = PBXBuildFile; fileRef = 32EA297812F1C88B42099501; }; E23C5C51305DC7CE30E4DAB7 = { isa = PBXBuildFile; fileRef = CB649686575473223C859482; }; - 89C96A721F3B54CF3F33848C = { isa = PBXBuildFile; fileRef = 7EBBC368FA350F786EF446B7; }; B92F53BABB6A9AC8348B001E = { isa = PBXBuildFile; fileRef = 78068AA59A5DCFCCAAEA79D0; }; EBC3AA015D24C62FA0307F51 = { isa = PBXBuildFile; fileRef = 61D06B694603F608CDA0703B; }; 803FFCA3DAC0C004A80143B4 = { isa = PBXBuildFile; fileRef = 91CB423DBC5F3CBEDD9CF2EF; }; @@ -834,8 +833,6 @@ CB649686575473223C859482 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_GlowEffect.cpp; path = ../../src/gui/graphics/effects/juce_GlowEffect.cpp; sourceTree = SOURCE_ROOT; }; FD1FA4ABB4226372235643E4 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_GlowEffect.h; path = ../../src/gui/graphics/effects/juce_GlowEffect.h; sourceTree = SOURCE_ROOT; }; 18DB9BD10F140F132A3279C3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ImageEffectFilter.h; path = ../../src/gui/graphics/effects/juce_ImageEffectFilter.h; sourceTree = SOURCE_ROOT; }; - 7EBBC368FA350F786EF446B7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_ReduceOpacityEffect.cpp; path = ../../src/gui/graphics/effects/juce_ReduceOpacityEffect.cpp; sourceTree = SOURCE_ROOT; }; - 8D18743ECC1BF12381811FD6 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ReduceOpacityEffect.h; path = ../../src/gui/graphics/effects/juce_ReduceOpacityEffect.h; sourceTree = SOURCE_ROOT; }; 78068AA59A5DCFCCAAEA79D0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_Font.cpp; path = ../../src/gui/graphics/fonts/juce_Font.cpp; sourceTree = SOURCE_ROOT; }; 0401EA0E883CCAAAC6960A27 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_Font.h; path = ../../src/gui/graphics/fonts/juce_Font.h; sourceTree = SOURCE_ROOT; }; 61D06B694603F608CDA0703B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_GlyphArrangement.cpp; path = ../../src/gui/graphics/fonts/juce_GlyphArrangement.cpp; sourceTree = SOURCE_ROOT; }; @@ -1592,9 +1589,7 @@ 85D4043F9E25047E07496DAC, CB649686575473223C859482, FD1FA4ABB4226372235643E4, - 18DB9BD10F140F132A3279C3, - 7EBBC368FA350F786EF446B7, - 8D18743ECC1BF12381811FD6 ); name = effects; sourceTree = ""; }; + 18DB9BD10F140F132A3279C3 ); name = effects; sourceTree = ""; }; 58FE42C578BFFD1F8F545B39 = { isa = PBXGroup; children = ( 78068AA59A5DCFCCAAEA79D0, 0401EA0E883CCAAAC6960A27, @@ -2143,7 +2138,6 @@ 645AF66C048A4815F5A8ECDD, 38EFE824E76B3BB99824C265, E23C5C51305DC7CE30E4DAB7, - 89C96A721F3B54CF3F33848C, B92F53BABB6A9AC8348B001E, EBC3AA015D24C62FA0307F51, 803FFCA3DAC0C004A80143B4, diff --git a/Juce.jucer b/Juce.jucer index 68122c0634..8d25866618 100644 --- a/Juce.jucer +++ b/Juce.jucer @@ -1083,10 +1083,6 @@ file="src/gui/graphics/effects/juce_GlowEffect.h"/> - - diff --git a/amalgamation/juce_amalgamated_template.cpp b/amalgamation/juce_amalgamated_template.cpp index 927d18cbe4..ff0b716ad6 100644 --- a/amalgamation/juce_amalgamated_template.cpp +++ b/amalgamation/juce_amalgamated_template.cpp @@ -350,7 +350,6 @@ #include "../src/gui/graphics/drawables/juce_SVGParser.cpp" #include "../src/gui/graphics/effects/juce_DropShadowEffect.cpp" #include "../src/gui/graphics/effects/juce_GlowEffect.cpp" - #include "../src/gui/graphics/effects/juce_ReduceOpacityEffect.cpp" #include "../src/gui/graphics/fonts/juce_Font.cpp" #include "../src/gui/graphics/fonts/juce_GlyphArrangement.cpp" #include "../src/gui/graphics/fonts/juce_TextLayout.cpp" diff --git a/extras/juce demo/Source/demos/WidgetsDemo.cpp b/extras/juce demo/Source/demos/WidgetsDemo.cpp index a73e35ee22..bdae8400ec 100644 --- a/extras/juce demo/Source/demos/WidgetsDemo.cpp +++ b/extras/juce demo/Source/demos/WidgetsDemo.cpp @@ -610,7 +610,9 @@ public: Random::getSystemRandom().nextInt (getHeight() / 2), 60 + Random::getSystemRandom().nextInt (getWidth() / 3), 16 + Random::getSystemRandom().nextInt (getHeight() / 6)), + Random::getSystemRandom().nextFloat(), 500 + Random::getSystemRandom().nextInt (2000), + false, Random::getSystemRandom().nextDouble(), Random::getSystemRandom().nextDouble()); } diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index f0e00a0584..a02f216efa 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -37491,15 +37491,17 @@ BEGIN_JUCE_NAMESPACE class ProcessorParameterPropertyComp : public PropertyComponent, public AudioProcessorListener, - public AsyncUpdater + public Timer { public: - ProcessorParameterPropertyComp (const String& name, AudioProcessor& owner_, int index_) + ProcessorParameterPropertyComp (const String& name, AudioProcessor& owner_, const int index_) : PropertyComponent (name), owner (owner_), index (index_), + paramHasChanged (false), slider (owner_, index_) { + startTimer (100); addAndMakeVisible (&slider); owner_.addListener (this); } @@ -37511,6 +37513,7 @@ public: void refresh() { + paramHasChanged = false; slider.setValue (owner.getParameter (index), false); } @@ -37519,12 +37522,20 @@ public: void audioProcessorParameterChanged (AudioProcessor*, int parameterIndex, float) { if (parameterIndex == index) - triggerAsyncUpdate(); + paramHasChanged = true; } - void handleAsyncUpdate() + void timerCallback() { - refresh(); + if (paramHasChanged) + { + refresh(); + startTimer (1000 / 50); + } + else + { + startTimer (jmin (1000 / 4, getTimerInterval() + 10)); + } } juce_UseDebuggingNewOperator @@ -37535,8 +37546,7 @@ private: { public: ParamSlider (AudioProcessor& owner_, const int index_) - : Slider (String::empty), - owner (owner_), + : owner (owner_), index (index_) { setRange (0.0, 1.0, 0.0); @@ -37545,10 +37555,6 @@ private: setScrollWheelEnabled (false); } - ~ParamSlider() - { - } - void valueChanged() { const float newVal = (float) getValue(); @@ -37574,6 +37580,7 @@ private: AudioProcessor& owner; const int index; + bool volatile paramHasChanged; ParamSlider slider; ProcessorParameterPropertyComp (const ProcessorParameterPropertyComp&); @@ -37586,7 +37593,7 @@ GenericAudioProcessorEditor::GenericAudioProcessorEditor (AudioProcessor* const jassert (owner_ != 0); setOpaque (true); - addAndMakeVisible (panel = new PropertyPanel()); + addAndMakeVisible (&panel); Array params; @@ -37604,14 +37611,13 @@ GenericAudioProcessorEditor::GenericAudioProcessorEditor (AudioProcessor* const totalHeight += pc->getPreferredHeight(); } - panel->addProperties (params); + panel.addProperties (params); setSize (400, jlimit (25, 400, totalHeight)); } GenericAudioProcessorEditor::~GenericAudioProcessorEditor() { - deleteAllChildren(); } void GenericAudioProcessorEditor::paint (Graphics& g) @@ -37621,7 +37627,7 @@ void GenericAudioProcessorEditor::paint (Graphics& g) void GenericAudioProcessorEditor::resized() { - panel->setSize (getWidth(), getHeight()); + panel.setBounds (getLocalBounds()); } END_JUCE_NAMESPACE @@ -39768,7 +39774,8 @@ Component::Component() bufferedImage_ (0), mouseListeners_ (0), keyListeners_ (0), - componentFlags_ (0) + componentFlags_ (0), + componentTransparency (0) { } @@ -39782,12 +39789,15 @@ Component::Component (const String& name) bufferedImage_ (0), mouseListeners_ (0), keyListeners_ (0), - componentFlags_ (0) + componentFlags_ (0), + componentTransparency (0) { } Component::~Component() { + static_jassert (sizeof (flags) <= sizeof (componentFlags_)); + componentListeners.call (&ComponentListener::componentBeingDeleted, *this); if (parentComponent_ != 0) @@ -39914,116 +39924,6 @@ bool Component::isShowing() const return false; } -class FadeOutProxyComponent : public Component, - public Timer -{ -public: - FadeOutProxyComponent (Component* comp, - const int fadeLengthMs, - const int deltaXToMove, - const int deltaYToMove, - const float scaleFactorAtEnd) - : lastTime (0), - alpha (1.0f), - scale (1.0f) - { - image = comp->createComponentSnapshot (comp->getLocalBounds()); - setBounds (comp->getBounds()); - comp->getParentComponent()->addAndMakeVisible (this); - toBehind (comp); - - alphaChangePerMs = -1.0f / (float)fadeLengthMs; - - centreX = comp->getX() + comp->getWidth() * 0.5f; - xChangePerMs = deltaXToMove / (float)fadeLengthMs; - - centreY = comp->getY() + comp->getHeight() * 0.5f; - yChangePerMs = deltaYToMove / (float)fadeLengthMs; - - scaleChangePerMs = (scaleFactorAtEnd - 1.0f) / (float)fadeLengthMs; - - setInterceptsMouseClicks (false, false); - - // 30 fps is enough for a fade, but we need a higher rate if it's moving as well.. - startTimer (1000 / ((deltaXToMove == 0 && deltaYToMove == 0) ? 30 : 50)); - } - - ~FadeOutProxyComponent() - { - } - - void paint (Graphics& g) - { - g.setOpacity (alpha); - - g.drawImage (image, - 0, 0, getWidth(), getHeight(), - 0, 0, image.getWidth(), image.getHeight()); - } - - void timerCallback() - { - const uint32 now = Time::getMillisecondCounter(); - - if (lastTime == 0) - lastTime = now; - - const int msPassed = (now > lastTime) ? now - lastTime : 0; - lastTime = now; - - alpha += alphaChangePerMs * msPassed; - - if (alpha > 0) - { - if (xChangePerMs != 0.0f || yChangePerMs != 0.0f || scaleChangePerMs != 0.0f) - { - centreX += xChangePerMs * msPassed; - centreY += yChangePerMs * msPassed; - scale += scaleChangePerMs * msPassed; - - const int w = roundToInt (image.getWidth() * scale); - const int h = roundToInt (image.getHeight() * scale); - - setBounds (roundToInt (centreX) - w / 2, - roundToInt (centreY) - h / 2, - w, h); - } - - repaint(); - } - else - { - delete this; - } - } - - juce_UseDebuggingNewOperator - -private: - Image image; - uint32 lastTime; - float alpha, alphaChangePerMs; - float centreX, xChangePerMs; - float centreY, yChangePerMs; - float scale, scaleChangePerMs; - - FadeOutProxyComponent (const FadeOutProxyComponent&); - FadeOutProxyComponent& operator= (const FadeOutProxyComponent&); -}; - -void Component::fadeOutComponent (const int millisecondsToFade, - const int deltaXToMove, - const int deltaYToMove, - const float scaleFactorAtEnd) -{ - //xxx won't work for comps without parents - if (isShowing() && millisecondsToFade > 0) - new FadeOutProxyComponent (this, millisecondsToFade, - deltaXToMove, deltaYToMove, scaleFactorAtEnd); - - setVisible (false); -} - bool Component::isValidComponent() const { return (this != 0) && isValidMessageListener(); @@ -41146,6 +41046,33 @@ void Component::setRepaintsOnMouseActivity (const bool shouldRepaint) throw() flags.repaintOnMouseActivityFlag = shouldRepaint; } +void Component::setAlpha (const float newAlpha) +{ + const uint8 newIntAlpha = (uint8) (255 - jlimit (0, 255, roundToInt (newAlpha * 255.0))); + + if (componentTransparency != newIntAlpha) + { + componentTransparency = newIntAlpha; + + if (flags.hasHeavyweightPeerFlag) + { + ComponentPeer* const peer = getPeer(); + + if (peer != 0) + peer->setAlpha (newAlpha); + } + else + { + repaint(); + } + } +} + +float Component::getAlpha() const +{ + return (255 - componentTransparency) / 255.0f; +} + void Component::repaintParent() { if (flags.visibleFlag) @@ -41238,7 +41165,7 @@ void Component::renderComponent (Graphics& g) paint (imG); } - g.setColour (Colours::black); + g.setColour (Colours::black.withAlpha (getAlpha())); g.drawImageAt (bufferedImage_, 0, 0); } else @@ -41257,8 +41184,7 @@ void Component::renderComponent (Graphics& g) { g.saveState(); - if (g.reduceClipRegion (child->getX(), child->getY(), - child->getWidth(), child->getHeight())) + if (g.reduceClipRegion (child->getBounds())) { for (int j = i + 1; j < childComponentList_.size(); ++j) { @@ -41271,7 +41197,7 @@ void Component::renderComponent (Graphics& g) if (! g.isClipEmpty()) { g.setOrigin (child->getX(), child->getY()); - child->paintEntireComponent (g); + child->paintEntireComponent (g, false); } } @@ -41284,34 +41210,53 @@ void Component::renderComponent (Graphics& g) g.restoreState(); } -void Component::paintEntireComponent (Graphics& g) +void Component::paintEntireComponent (Graphics& g, bool ignoreAlphaLevel) { jassert (! g.isClipEmpty()); -#if JUCE_DEBUG + #if JUCE_DEBUG flags.isInsidePaintCall = true; -#endif + #endif if (effect_ != 0) { Image effectImage (flags.opaqueFlag ? Image::RGB : Image::ARGB, - getWidth(), getHeight(), - ! flags.opaqueFlag, Image::NativeImage); + getWidth(), getHeight(), ! flags.opaqueFlag, Image::NativeImage); { Graphics g2 (effectImage); renderComponent (g2); } - effect_->applyEffect (effectImage, g); + effect_->applyEffect (effectImage, g, ignoreAlphaLevel ? 1.0f : getAlpha()); } else { - renderComponent (g); + if (componentTransparency > 0 && ! ignoreAlphaLevel) + { + if (componentTransparency < 255) + { + Image temp (flags.opaqueFlag ? Image::RGB : Image::ARGB, + getWidth(), getHeight(), ! flags.opaqueFlag, Image::NativeImage); + + { + Graphics tempG (temp); + tempG.reduceClipRegion (g.getClipBounds()); + paintEntireComponent (tempG, true); + } + + g.setColour (Colours::black.withAlpha (getAlpha())); + g.drawImageAt (temp, 0, 0); + } + } + else + { + renderComponent (g); + } } -#if JUCE_DEBUG + #if JUCE_DEBUG flags.isInsidePaintCall = false; -#endif + #endif } const Image Component::createComponentSnapshot (const Rectangle& areaToGrab, @@ -41329,7 +41274,7 @@ const Image Component::createComponentSnapshot (const Rectangle& areaToGrab Graphics imageContext (componentImage); imageContext.setOrigin (-r.getX(), -r.getY()); - paintEntireComponent (imageContext); + paintEntireComponent (imageContext, true); return componentImage; } @@ -49500,8 +49445,8 @@ const Image ListBox::createSnapshotOfSelectedRows (int& imageX, int& imageY) Graphics g (snapshot); g.setOrigin (pos.getX() - imageX, pos.getY() - imageY); - if (g.reduceClipRegion (0, 0, rowComp->getWidth(), rowComp->getHeight())) - rowComp->paintEntireComponent (g); + if (g.reduceClipRegion (rowComp->getLocalBounds())) + rowComp->paintEntireComponent (g, false); } } @@ -55311,7 +55256,6 @@ Toolbar::Toolbar() Toolbar::~Toolbar() { - animator.cancelAllAnimations (true); deleteAllChildren(); } @@ -55581,11 +55525,11 @@ void Toolbar::updateAllItemPositions (const bool animate) if (animate) { - animator.animateComponent (tc, newBounds, 200, 3.0, 0.0); + Desktop::getInstance().getAnimator().animateComponent (tc, newBounds, 1.0f, 200, false, 3.0, 0.0); } else { - animator.cancelAnimation (tc, false); + Desktop::getInstance().getAnimator().cancelAnimation (tc, false); tc->setBounds (newBounds); } @@ -55671,12 +55615,13 @@ void Toolbar::itemDragMove (const String&, Component* sourceComponent, int x, in const int dragObjectLeft = vertical ? (y - tc->dragOffsetY) : (x - tc->dragOffsetX); const int dragObjectRight = dragObjectLeft + (vertical ? tc->getHeight() : tc->getWidth()); - const Rectangle current (animator.getComponentDestination (getChildComponent (newIndex))); + const Rectangle current (Desktop::getInstance().getAnimator() + .getComponentDestination (getChildComponent (newIndex))); ToolbarItemComponent* const prev = getNextActiveComponent (newIndex, -1); if (prev != 0) { - const Rectangle previousPos (animator.getComponentDestination (prev)); + const Rectangle previousPos (Desktop::getInstance().getAnimator().getComponentDestination (prev)); if (abs (dragObjectLeft - (vertical ? previousPos.getY() : previousPos.getX()) < abs (dragObjectRight - (vertical ? current.getBottom() : current.getRight())))) @@ -55688,7 +55633,7 @@ void Toolbar::itemDragMove (const String&, Component* sourceComponent, int x, in ToolbarItemComponent* const next = getNextActiveComponent (newIndex, 1); if (next != 0) { - const Rectangle nextPos (animator.getComponentDestination (next)); + const Rectangle nextPos (Desktop::getInstance().getAnimator().getComponentDestination (next)); if (abs (dragObjectLeft - (vertical ? current.getY() : current.getX()) > abs (dragObjectRight - (vertical ? nextPos.getBottom() : nextPos.getRight())))) @@ -56110,8 +56055,8 @@ void ToolbarItemComponent::paintButton (Graphics& g, const bool over, const bool if (! contentArea.isEmpty()) { g.saveState(); + g.reduceClipRegion (contentArea); g.setOrigin (contentArea.getX(), contentArea.getY()); - g.reduceClipRegion (0, 0, contentArea.getWidth(), contentArea.getHeight()); paintButtonArea (g, contentArea.getWidth(), contentArea.getHeight(), over, down); @@ -60615,7 +60560,8 @@ private: KeyMappingEditorComponent::KeyMappingEditorComponent (KeyPressMappingSet* const mappingManager, const bool showResetToDefaultButton) - : mappings (mappingManager) + : mappings (mappingManager), + resetButton (TRANS ("reset to defaults")) { jassert (mappingManager != 0); // can't be null! @@ -60623,25 +60569,22 @@ KeyMappingEditorComponent::KeyMappingEditorComponent (KeyPressMappingSet* const setLinesDrawnForSubItems (false); - resetButton = 0; - if (showResetToDefaultButton) { - addAndMakeVisible (resetButton = new TextButton (TRANS("reset to defaults"))); - resetButton->addButtonListener (this); + addAndMakeVisible (&resetButton); + resetButton.addButtonListener (this); } - addAndMakeVisible (tree = new TreeView()); - tree->setColour (TreeView::backgroundColourId, findColour (backgroundColourId)); - tree->setRootItemVisible (false); - tree->setDefaultOpenness (true); - tree->setRootItem (this); + addAndMakeVisible (&tree); + tree.setColour (TreeView::backgroundColourId, findColour (backgroundColourId)); + tree.setRootItemVisible (false); + tree.setDefaultOpenness (true); + tree.setRootItem (this); } KeyMappingEditorComponent::~KeyMappingEditorComponent() { mappings->removeChangeListener (this); - deleteAllChildren(); } bool KeyMappingEditorComponent::mightContainSubItems() @@ -60659,7 +60602,7 @@ void KeyMappingEditorComponent::setColours (const Colour& mainBackground, { setColour (backgroundColourId, mainBackground); setColour (textColourId, textColour); - tree->setColour (TreeView::backgroundColourId, mainBackground); + tree.setColour (TreeView::backgroundColourId, mainBackground); } void KeyMappingEditorComponent::parentHierarchyChanged() @@ -60671,22 +60614,22 @@ void KeyMappingEditorComponent::resized() { int h = getHeight(); - if (resetButton != 0) + if (resetButton.isVisible()) { const int buttonHeight = 20; h -= buttonHeight + 8; int x = getWidth() - 8; - resetButton->changeWidthToFitText (buttonHeight); - resetButton->setTopRightPosition (x, h + 6); + resetButton.changeWidthToFitText (buttonHeight); + resetButton.setTopRightPosition (x, h + 6); } - tree->setBounds (0, 0, getWidth(), h); + tree.setBounds (0, 0, getWidth(), h); } void KeyMappingEditorComponent::buttonClicked (Button* button) { - if (button == resetButton) + if (button == &resetButton) { if (AlertWindow::showOkCancelBox (AlertWindow::QuestionIcon, TRANS("Reset to defaults"), @@ -60700,7 +60643,7 @@ void KeyMappingEditorComponent::buttonClicked (Button* button) void KeyMappingEditorComponent::changeListenerCallback (void*) { - ScopedPointer oldOpenness (tree->getOpennessState (true)); + ScopedPointer oldOpenness (tree.getOpennessState (true)); clearSubItems(); @@ -60720,7 +60663,7 @@ void KeyMappingEditorComponent::changeListenerCallback (void*) } if (oldOpenness != 0) - tree->restoreOpennessState (*oldOpenness); + tree.restoreOpennessState (*oldOpenness); } class KeyEntryWindow : public AlertWindow @@ -61541,59 +61484,158 @@ public: { } + void reset (const Rectangle& finalBounds, + float finalAlpha, + int millisecondsToSpendMoving, + bool useProxyComponent, + double startSpeed_, double endSpeed_) + { + msElapsed = 0; + msTotal = jmax (1, millisecondsToSpendMoving); + lastProgress = 0; + destination = finalBounds; + destAlpha = finalAlpha; + + isMoving = (finalBounds != component->getBounds()); + isChangingAlpha = (finalAlpha != component->getAlpha()); + + left = component->getX(); + top = component->getY(); + right = component->getRight(); + bottom = component->getBottom(); + alpha = component->getAlpha(); + + const double invTotalDistance = 4.0 / (startSpeed_ + endSpeed_ + 2.0); + startSpeed = jmax (0.0, startSpeed_ * invTotalDistance); + midSpeed = invTotalDistance; + endSpeed = jmax (0.0, endSpeed_ * invTotalDistance); + + if (useProxyComponent) + proxy = new ProxyComponent (*component); + else + proxy = 0; + + component->setVisible (! useProxyComponent); + } + bool useTimeslice (const int elapsed) { - if (component == 0) - return false; + Component* const c = proxy != 0 ? static_cast (proxy) + : static_cast (component); - msElapsed += elapsed; - double newProgress = msElapsed / (double) msTotal; - - if (newProgress >= 0 && newProgress < 1.0) + if (c != 0) { - newProgress = timeToDistance (newProgress); - const double delta = (newProgress - lastProgress) / (1.0 - lastProgress); - jassert (newProgress >= lastProgress); - lastProgress = newProgress; + msElapsed += elapsed; + double newProgress = msElapsed / (double) msTotal; - left += (destination.getX() - left) * delta; - top += (destination.getY() - top) * delta; - right += (destination.getRight() - right) * delta; - bottom += (destination.getBottom() - bottom) * delta; - - if (delta < 1.0) + if (newProgress >= 0 && newProgress < 1.0) { - const Rectangle newBounds (roundToInt (left), - roundToInt (top), - roundToInt (right - left), - roundToInt (bottom - top)); + newProgress = timeToDistance (newProgress); + const double delta = (newProgress - lastProgress) / (1.0 - lastProgress); + jassert (newProgress >= lastProgress); + lastProgress = newProgress; - if (newBounds != destination) + if (delta < 1.0) { - component->setBounds (newBounds); - return true; + bool stillBusy = false; + + if (isMoving) + { + left += (destination.getX() - left) * delta; + top += (destination.getY() - top) * delta; + right += (destination.getRight() - right) * delta; + bottom += (destination.getBottom() - bottom) * delta; + + const Rectangle newBounds (roundToInt (left), + roundToInt (top), + roundToInt (right - left), + roundToInt (bottom - top)); + + if (newBounds != destination) + { + c->setBounds (newBounds); + stillBusy = true; + } + } + + if (isChangingAlpha) + { + alpha += (destAlpha - alpha) * delta; + c->setAlpha ((float) alpha); + stillBusy = true; + } + + if (stillBusy) + return true; } } } - component->setBounds (destination); + moveToFinalDestination(); return false; } void moveToFinalDestination() { if (component != 0) + { + component->setAlpha ((float) destAlpha); component->setBounds (destination); + } } + class ProxyComponent : public Component + { + public: + ProxyComponent (Component& component) + : image (component.createComponentSnapshot (component.getLocalBounds())) + { + setBounds (component.getBounds()); + setAlpha (component.getAlpha()); + setInterceptsMouseClicks (false, false); + + Component* const parent = component.getParentComponent(); + + if (parent != 0) + parent->addAndMakeVisible (this); + else if (component.isOnDesktop() && component.getPeer() != 0) + addToDesktop (component.getPeer()->getStyleFlags()); + else + jassertfalse; // seem to be trying to animate a component that's not visible.. + + setVisible (true); + toBehind (&component); + } + + void paint (Graphics& g) + { + g.setOpacity (1.0f); + g.drawImage (image, 0, 0, getWidth(), getHeight(), + 0, 0, image.getWidth(), image.getHeight()); + } + + juce_UseDebuggingNewOperator + + private: + Image image; + + ProxyComponent (const ProxyComponent&); + ProxyComponent& operator= (const ProxyComponent&); + }; + Component::SafePointer component; + ScopedPointer proxy; + Rectangle destination; + double destAlpha; + int msElapsed, msTotal; double startSpeed, midSpeed, endSpeed, lastProgress; - double left, top, right, bottom; + double left, top, right, bottom, alpha; + bool isMoving, isChangingAlpha; private: - inline double timeToDistance (const double time) const + double timeToDistance (const double time) const throw() { return (time < 0.5) ? time * (startSpeed + time * (midSpeed - startSpeed)) : 0.5 * (startSpeed + 0.5 * (midSpeed - startSpeed)) @@ -61620,11 +61662,16 @@ ComponentAnimator::AnimationTask* ComponentAnimator::findTaskFor (Component* con } void ComponentAnimator::animateComponent (Component* const component, - const Rectangle& finalPosition, + const Rectangle& finalBounds, + const float finalAlpha, const int millisecondsToSpendMoving, + const bool useProxyComponent, const double startSpeed, const double endSpeed) { + // the speeds must be 0 or greater! + jassert (startSpeed >= 0 && endSpeed >= 0) + if (component != 0) { AnimationTask* at = findTaskFor (component); @@ -61636,23 +61683,8 @@ void ComponentAnimator::animateComponent (Component* const component, sendChangeMessage (this); } - at->msElapsed = 0; - at->lastProgress = 0; - at->msTotal = jmax (1, millisecondsToSpendMoving); - at->destination = finalPosition; - - // the speeds must be 0 or greater! - jassert (startSpeed >= 0 && endSpeed >= 0) - - const double invTotalDistance = 4.0 / (startSpeed + endSpeed + 2.0); - at->startSpeed = jmax (0.0, startSpeed * invTotalDistance); - at->midSpeed = invTotalDistance; - at->endSpeed = jmax (0.0, endSpeed * invTotalDistance); - - at->left = component->getX(); - at->top = component->getY(); - at->right = component->getRight(); - at->bottom = component->getBottom(); + at->reset (finalBounds, finalAlpha, millisecondsToSpendMoving, + useProxyComponent, startSpeed, endSpeed); if (! isTimerRunning()) { @@ -61662,6 +61694,27 @@ void ComponentAnimator::animateComponent (Component* const component, } } +void ComponentAnimator::fadeOut (Component* component, int millisecondsToTake) +{ + if (component != 0) + { + if (component->isShowing() && millisecondsToTake > 0) + animateComponent (component, component->getBounds(), 0.0f, millisecondsToTake, true, 1.0, 1.0); + + component->setVisible (false); + } +} + +void ComponentAnimator::fadeIn (Component* component, int millisecondsToTake) +{ + if (component != 0 && ! (component->isVisible() && component->getAlpha() == 1.0f)) + { + component->setAlpha (0.0f); + component->setVisible (true); + animateComponent (component, component->getBounds(), 1.0f, millisecondsToTake, false, 1.0, 1.0); + } +} + void ComponentAnimator::cancelAllAnimations (const bool moveComponentsToTheirFinalPositions) { if (tasks.size() > 0) @@ -61692,14 +61745,13 @@ void ComponentAnimator::cancelAnimation (Component* const component, const Rectangle ComponentAnimator::getComponentDestination (Component* const component) { + jassert (component != 0); AnimationTask* const at = findTaskFor (component); if (at != 0) return at->destination; - else if (component != 0) - return component->getBounds(); - return Rectangle(); + return component->getBounds(); } bool ComponentAnimator::isAnimating (Component* component) const @@ -67553,7 +67605,7 @@ void LookAndFeel::drawCallOutBoxBackground (CallOutBox& box, Graphics& g, const DropShadowEffect shadow; shadow.setShadowProperties (5.0f, 0.4f, 0, 2); - shadow.applyEffect (content, g); + shadow.applyEffect (content, g, 1.0f); } void LookAndFeel::createFileChooserHeaderText (const String& title, @@ -69455,7 +69507,7 @@ public: } // hide this and all sub-comps - void hide (const PopupMenu::Item* const item) + void hide (const PopupMenu::Item* const item, const bool makeInvisible) { if (isVisible()) { @@ -69465,7 +69517,9 @@ public: currentChild = 0; exitModalState (item != 0 ? item->itemId : 0); - setVisible (false); + + if (makeInvisible) + setVisible (false); if (item != 0 && item->commandManager != 0 @@ -69488,11 +69542,11 @@ public: { // need a copy of this on the stack as the one passed in will get deleted during this call const PopupMenu::Item mi (*item); - hide (&mi); + hide (&mi, false); } else { - hide (0); + hide (0, false); } } } @@ -69540,7 +69594,7 @@ public: Component::SafePointer parentWindow (owner); PopupMenu::ItemComponent* currentChildOfParent = parentWindow->currentChild; - hide (0); + hide (0, true); if (parentWindow != 0) parentWindow->setCurrentlyHighlightedChild (currentChildOfParent); @@ -69698,7 +69752,7 @@ public: if (hideOnExit && hasBeenOver && ! isOverAny) { - hide (0); + hide (0, true); } else { @@ -70226,7 +70280,7 @@ private: { if (isOver && (c != 0) && (activeSubMenu != 0)) { - activeSubMenu->hide (0); + activeSubMenu->hide (0, true); } if (! isOver) @@ -70532,6 +70586,9 @@ public: managerOfChosenCommand->invoke (info, true); } + + // (this would be the place to fade out the component, if that's what's required) + component = 0; } ApplicationCommandManager* managerOfChosenCommand; @@ -70968,19 +71025,17 @@ public: if (dropAccepted || source == 0) { - fadeOutComponent (120); + Desktop::getInstance().getAnimator().fadeOut (this, 120); } else { - const Point target (source->relativePositionToGlobal (Point (source->getWidth() / 2, - source->getHeight() / 2))); + const Point target (source->relativePositionToGlobal (source->getLocalBounds().getCentre())); + const Point ourCentre (relativePositionToGlobal (getLocalBounds().getCentre())); - const Point ourCentre (relativePositionToGlobal (Point (getWidth() / 2, - getHeight() / 2))); - - fadeOutComponent (120, - target.getX() - ourCentre.getX(), - target.getY() - ourCentre.getY()); + Desktop::getInstance().getAnimator().animateComponent (this, + getBounds() + (target - ourCentre), + 0.0f, 120, + true, 1.0, 1.0); } } @@ -72965,10 +73020,6 @@ BEGIN_JUCE_NAMESPACE class TextPropLabel : public Label { - TextPropertyComponent& owner; - int maxChars; - bool isMultiline; - public: TextPropLabel (TextPropertyComponent& owner_, const int maxChars_, const bool isMultiline_) @@ -72983,14 +73034,9 @@ public: setColour (outlineColourId, findColour (ComboBox::outlineColourId)); } - ~TextPropLabel() - { - } - TextEditor* createEditorComponent() { TextEditor* const textEditor = Label::createEditorComponent(); - textEditor->setInputRestrictions (maxChars); if (isMultiline) @@ -73006,6 +73052,11 @@ public: { owner.textWasEdited(); } + +private: + TextPropertyComponent& owner; + int maxChars; + bool isMultiline; }; TextPropertyComponent::TextPropertyComponent (const String& name, @@ -73029,7 +73080,6 @@ TextPropertyComponent::TextPropertyComponent (const Value& valueToControl, TextPropertyComponent::~TextPropertyComponent() { - deleteAllChildren(); } void TextPropertyComponent::setText (const String& newText) @@ -74242,18 +74292,8 @@ void BubbleComponent::setPosition (const int arrowTipX_, void BubbleComponent::setPosition (const Rectangle& rectangleToPointTo) { - Rectangle availableSpace; - - if (getParentComponent() != 0) - { - availableSpace.setSize (getParentComponent()->getWidth(), - getParentComponent()->getHeight()); - } - else - { - availableSpace = getParentMonitorArea(); - } - + Rectangle availableSpace (getParentComponent() != 0 ? getParentComponent()->getLocalBounds() + : getParentMonitorArea()); int x = 0; int y = 0; int w = 150; @@ -74348,7 +74388,7 @@ BubbleMessageComponent::BubbleMessageComponent (int fadeOutLengthMs) BubbleMessageComponent::~BubbleMessageComponent() { - fadeOutComponent (fadeOutLength); + Desktop::getInstance().getAnimator().fadeOut (this, fadeOutLength); } void BubbleMessageComponent::showAt (int x, int y, @@ -74430,10 +74470,11 @@ void BubbleMessageComponent::timerCallback() else if (expiryTime != 0 && Time::getMillisecondCounter() > expiryTime) { stopTimer(); - fadeOutComponent (fadeOutLength); if (deleteAfterUse) delete this; + else + Desktop::getInstance().getAnimator().fadeOut (this, fadeOutLength); } } @@ -75359,6 +75400,7 @@ public: void setSize (int, int) {} void setBounds (int, int, int, int, bool) {} void setMinimised (bool) {} + void setAlpha (float /*newAlpha*/) {} bool isMinimised() const { return false; } void setFullScreen (bool) {} bool isFullScreen() const { return false; } @@ -75564,12 +75606,13 @@ void MagnifierComponent::paint (Graphics& g) } Image temp (Image::ARGB, jmax (w, srcX + srcW), jmax (h, srcY + srcH), false); - temp.clear (Rectangle (srcX, srcY, srcW, srcH)); + const Rectangle area (srcX, srcY, srcW, srcH); + temp.clear (area); { Graphics g2 (temp); - g2.reduceClipRegion (srcX, srcY, srcW, srcH); - holderComp->paintEntireComponent (g2); + g2.reduceClipRegion (area); + holderComp->paintEntireComponent (g2, false); } g.setImageResamplingQuality (quality); @@ -77963,7 +78006,7 @@ void ComponentPeer::handlePaint (LowLevelGraphicsContext& contextToPaintTo) JUCE_TRY { - component->paintEntireComponent (g); + component->paintEntireComponent (g, true); } JUCE_CATCH_EXCEPTION @@ -78623,8 +78666,8 @@ void DocumentWindow::paint (Graphics& g) } const Rectangle titleBarArea (getTitleBarArea()); + g.reduceClipRegion (titleBarArea); g.setOrigin (titleBarArea.getX(), titleBarArea.getY()); - g.reduceClipRegion (0, 0, titleBarArea.getWidth(), titleBarArea.getHeight()); int titleSpaceX1 = 6; int titleSpaceX2 = titleBarArea.getWidth() - 6; @@ -82505,10 +82548,15 @@ bool Graphics::isVectorDevice() const return context->isVectorDevice(); } -bool Graphics::reduceClipRegion (const int x, const int y, const int w, const int h) +bool Graphics::reduceClipRegion (const Rectangle& area) { saveStateIfPending(); - return context->clipToRectangle (Rectangle (x, y, w, h)); + return context->clipToRectangle (area); +} + +bool Graphics::reduceClipRegion (const int x, const int y, const int w, const int h) +{ + return reduceClipRegion (Rectangle (x, y, w, h)); } bool Graphics::reduceClipRegion (const RectangleList& clipRegion) @@ -85502,9 +85550,8 @@ public: ColourGradient g2 (*(fillType.gradient)); g2.multiplyOpacity (fillType.getOpacity()); - g2.point1.addXY (-0.5f, -0.5f); - g2.point2.addXY (-0.5f, -0.5f); - AffineTransform transform (fillType.transform.translated ((float) xOffset, (float) yOffset)); + AffineTransform transform (fillType.transform.translated (xOffset - 0.5f, yOffset - 0.5f)); + const bool isIdentity = transform.isOnlyTranslation(); if (isIdentity) @@ -86215,7 +86262,7 @@ void DrawableShape::setBrush (const Drawable::RenderingContext& context, const F } bool DrawableShape::refreshFillTypes (const FillAndStrokeState& newState, - Expression::EvaluationContext* nameFinder, + Expression::EvaluationContext* /*nameFinder*/, ImageProvider* imageProvider) { bool hasChanged = false; @@ -87173,6 +87220,8 @@ const Rectangle DrawableComposite::refreshFromValueTree (const ValueTree& } } + invalidatePoints(); + if (redrawAll) damage = damage.getUnion (getBounds()); else if (! damage.isEmpty()) @@ -87969,8 +88018,8 @@ bool DrawableRectangle::rebuildPath (Path& path) const const float w = Line (points[0], points[1]).getLength(); const float h = Line (points[0], points[2]).getLength(); - const float cornerSizeX = cornerSize.x.resolve (parent); - const float cornerSizeY = cornerSize.y.resolve (parent); + const float cornerSizeX = (float) cornerSize.x.resolve (parent); + const float cornerSizeY = (float) cornerSize.y.resolve (parent); path.clear(); @@ -89618,7 +89667,7 @@ void DropShadowEffect::setShadowProperties (const float newRadius, opacity = newOpacity; } -void DropShadowEffect::applyEffect (Image& image, Graphics& g) +void DropShadowEffect::applyEffect (Image& image, Graphics& g, float alpha) { const int w = image.getWidth(); const int h = image.getHeight(); @@ -89660,10 +89709,10 @@ void DropShadowEffect::applyEffect (Image& image, Graphics& g) } } - g.setColour (Colours::black.withAlpha (opacity)); + g.setColour (Colours::black.withAlpha (opacity * alpha)); g.drawImageAt (shadowImage, offsetX, offsetY, true); - g.setOpacity (1.0f); + g.setOpacity (alpha); g.drawImageAt (image, 0, 0); } @@ -89695,7 +89744,7 @@ void GlowEffect::setGlowProperties (const float newRadius, colour = newColour; } -void GlowEffect::applyEffect (Image& image, Graphics& g) +void GlowEffect::applyEffect (Image& image, Graphics& g, float alpha) { Image temp (image.getFormat(), image.getWidth(), image.getHeight(), true); @@ -89706,10 +89755,10 @@ void GlowEffect::applyEffect (Image& image, Graphics& g) blurKernel.applyToImage (temp, image, image.getBounds()); - g.setColour (colour); + g.setColour (colour.withMultipliedAlpha (alpha)); g.drawImageAt (temp, 0, 0, true); - g.setOpacity (1.0f); + g.setOpacity (alpha); g.drawImageAt (image, 0, 0, false); } @@ -89717,33 +89766,6 @@ END_JUCE_NAMESPACE /*** End of inlined file: juce_GlowEffect.cpp ***/ -/*** Start of inlined file: juce_ReduceOpacityEffect.cpp ***/ -BEGIN_JUCE_NAMESPACE - -ReduceOpacityEffect::ReduceOpacityEffect (const float opacity_) - : opacity (opacity_) -{ -} - -ReduceOpacityEffect::~ReduceOpacityEffect() -{ -} - -void ReduceOpacityEffect::setOpacity (const float newOpacity) -{ - opacity = jlimit (0.0f, 1.0f, newOpacity); -} - -void ReduceOpacityEffect::applyEffect (Image& image, Graphics& g) -{ - g.setOpacity (opacity); - g.drawImageAt (image, 0, 0); -} - -END_JUCE_NAMESPACE -/*** End of inlined file: juce_ReduceOpacityEffect.cpp ***/ - - /*** Start of inlined file: juce_Font.cpp ***/ BEGIN_JUCE_NAMESPACE @@ -241941,7 +241963,8 @@ public: void blitToWindow (HWND hwnd, HDC dc, const bool transparent, const int x, const int y, - const RectangleList& maskedRegion) throw() + const RectangleList& maskedRegion, + const uint8 updateLayeredWindowAlpha) throw() { static HDRAWDIB hdd = 0; static bool needToCreateDrawDib = true; @@ -241999,7 +242022,7 @@ public: bf.AlphaFormat = AC_SRC_ALPHA; bf.BlendFlags = 0; bf.BlendOp = AC_SRC_OVER; - bf.SourceConstantAlpha = 0xff; + bf.SourceConstantAlpha = updateLayeredWindowAlpha; if (! maskedRegion.isEmpty()) { @@ -242115,6 +242138,7 @@ public: hasCreatedCaret (false), currentWindowIcon (0), dropTarget (0), + updateLayeredWindowAlpha (255), parentToAddTo (parentToAddTo_) { callFunctionIfNotLocked (&createWindowCallback, this); @@ -242188,7 +242212,7 @@ public: void repaintNowIfTransparent() { - if (isTransparent() && lastPaintTime > 0 && Time::getMillisecondCounter() > lastPaintTime + 30) + if (isUsingUpdateLayeredWindow() && lastPaintTime > 0 && Time::getMillisecondCounter() > lastPaintTime + 30) handlePaintMessage(); } @@ -242275,6 +242299,30 @@ public: return screenPosition - getScreenPosition(); } + void setAlpha (float newAlpha) + { + const uint8 intAlpha = (uint8) jlimit (0, 255, (int) (newAlpha * 255.0f)); + + if (component->isOpaque()) + { + if (newAlpha < 1.0f) + { + SetWindowLong (hwnd, GWL_EXSTYLE, GetWindowLong (hwnd, GWL_EXSTYLE) | WS_EX_LAYERED); + SetLayeredWindowAttributes (hwnd, RGB (0, 0, 0), intAlpha, LWA_ALPHA); + } + else + { + SetWindowLong (hwnd, GWL_EXSTYLE, GetWindowLong (hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED); + RedrawWindow (hwnd, 0, 0, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN); + } + } + else + { + updateLayeredWindowAlpha = intAlpha; + component->repaint(); + } + } + void setMinimised (bool shouldBeMinimised) { if (shouldBeMinimised != isMinimised()) @@ -242578,6 +242626,7 @@ private: HICON currentWindowIcon; ScopedPointer taskBarIcon; IDropTarget* dropTarget; + uint8 updateLayeredWindowAlpha; class TemporaryImage : public Timer { @@ -242739,6 +242788,10 @@ private: // Calling this function here is (for some reason) necessary to make Windows // correctly enable the menu items that we specify in the wm_initmenu message. GetSystemMenu (hwnd, false); + + const float alpha = component->getAlpha(); + if (alpha < 1.0f) + setAlpha (alpha); } else { @@ -242778,7 +242831,7 @@ private: void offsetWithinParent (int& x, int& y) const { - if (isTransparent()) + if (isUsingUpdateLayeredWindow()) { HWND parentHwnd = GetParent (hwnd); @@ -242792,9 +242845,9 @@ private: } } - bool isTransparent() const + bool isUsingUpdateLayeredWindow() const { - return (GetWindowLong (hwnd, GWL_EXSTYLE) & WS_EX_LAYERED) != 0; + return ! component->isOpaque(); } inline bool hasTitleBar() const throw() { return (styleFlags & windowHasTitleBar) != 0; } @@ -242858,7 +242911,7 @@ private: int w = paintStruct.rcPaint.right - x; int h = paintStruct.rcPaint.bottom - y; - const bool transparent = isTransparent(); + const bool transparent = isUsingUpdateLayeredWindow(); if (transparent) { @@ -242949,7 +243002,7 @@ private: if (! dontRepaint) static_cast (offscreenImage.getSharedImage()) - ->blitToWindow (hwnd, dc, transparent, x, y, maskedRegion); + ->blitToWindow (hwnd, dc, transparent, x, y, maskedRegion, updateLayeredWindowAlpha); } DeleteObject (rgn); @@ -243564,7 +243617,12 @@ private: return 0; case WM_WINDOWPOSCHANGED: - doMouseEvent (getCurrentMousePos()); + { + const Point pos (getCurrentMousePos()); + if (contains (pos, false)) + doMouseEvent (pos); + } + handleMovedOrResized(); if (dontRepaint) @@ -243902,13 +243960,13 @@ const ModifierKeys ModifierKeys::getCurrentModifiersRealtime() throw() { Win32ComponentPeer::updateKeyModifiers(); - int keyMods = 0; - if ((GetKeyState (VK_LBUTTON) & 0x8000) != 0) keyMods |= ModifierKeys::leftButtonModifier; - if ((GetKeyState (VK_RBUTTON) & 0x8000) != 0) keyMods |= ModifierKeys::rightButtonModifier; - if ((GetKeyState (VK_MBUTTON) & 0x8000) != 0) keyMods |= ModifierKeys::middleButtonModifier; + int mouseMods = 0; + if ((GetKeyState (VK_LBUTTON) & 0x8000) != 0) mouseMods |= ModifierKeys::leftButtonModifier; + if ((GetKeyState (VK_RBUTTON) & 0x8000) != 0) mouseMods |= ModifierKeys::rightButtonModifier; + if ((GetKeyState (VK_MBUTTON) & 0x8000) != 0) mouseMods |= ModifierKeys::middleButtonModifier; Win32ComponentPeer::currentModifiers - = Win32ComponentPeer::currentModifiers.withOnlyMouseButtons().withFlags (keyMods); + = Win32ComponentPeer::currentModifiers.withoutMouseButtons().withFlags (mouseMods); return Win32ComponentPeer::currentModifiers; } @@ -258738,6 +258796,11 @@ public: return screenPosition - getScreenPosition(); } + void setAlpha (float newAlpha) + { + //xxx todo! + } + void setMinimised (bool shouldBeMinimised) { if (shouldBeMinimised) @@ -267676,6 +267739,7 @@ public: const Point getScreenPosition() const; const Point relativePositionToGlobal (const Point& relativePosition); const Point globalPositionToRelative (const Point& screenPosition); + void setAlpha (float newAlpha); void setMinimised (bool shouldBeMinimised); bool isMinimised() const; void setFullScreen (bool shouldBeFullScreen); @@ -268128,6 +268192,11 @@ CGRect UIViewComponentPeer::constrainRect (CGRect r) return r; } +void UIViewComponentPeer::setAlpha (float newAlpha) +{ + [[view window] setAlpha: (CGFloat) newAlpha]; +} + void UIViewComponentPeer::setMinimised (bool shouldBeMinimised) { } @@ -272428,6 +272497,7 @@ public: const Point getScreenPosition() const; const Point relativePositionToGlobal (const Point& relativePosition); const Point globalPositionToRelative (const Point& screenPosition); + void setAlpha (float newAlpha); void setMinimised (bool shouldBeMinimised); bool isMinimised() const; void setFullScreen (bool shouldBeFullScreen); @@ -273132,8 +273202,6 @@ NSViewComponentPeer::NSViewComponentPeer (Component* const component_, { window = [viewToAttachTo window]; [viewToAttachTo addSubview: view]; - - setVisible (component->isVisible()); } else { @@ -273183,6 +273251,10 @@ NSViewComponentPeer::NSViewComponentPeer (Component* const component_, [window setIgnoresMouseEvents: (windowStyleFlags & windowIgnoresMouseClicks) != 0]; } + const float alpha = component->getAlpha(); + if (alpha < 1.0f) + setAlpha (alpha); + setTitle (component->getName()); } @@ -273345,6 +273417,14 @@ NSRect NSViewComponentPeer::constrainRect (NSRect r) return r; } +void NSViewComponentPeer::setAlpha (float newAlpha) +{ + if (! isSharedWindow) + [window setAlphaValue: (CGFloat) newAlpha]; + else + [view setAlphaValue: (CGFloat) newAlpha]; +} + void NSViewComponentPeer::setMinimised (bool shouldBeMinimised) { if (! isSharedWindow) diff --git a/juce_amalgamated.h b/juce_amalgamated.h index e64ea53828..41e78b4f19 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -64,7 +64,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 52 -#define JUCE_BUILDNUMBER 80 +#define JUCE_BUILDNUMBER 81 /** Current Juce version number. @@ -24909,6 +24909,13 @@ public: */ bool reduceClipRegion (int x, int y, int width, int height); + /** Intersects the current clipping region with another region. + + @returns true if the resulting clipping region is non-zero in size + @see setOrigin, clipRegionIntersects + */ + bool reduceClipRegion (const Rectangle& area); + /** Intersects the current clipping region with a rectangle list region. @returns true if the resulting clipping region is non-zero in size @@ -25019,9 +25026,12 @@ public: its paint() method. The image may or may not have an alpha channel, depending on whether the component is opaque. @param destContext the graphics context to use to draw the resultant image. + @param alpha the alpha with which to draw the resultant image to the + target context */ virtual void applyEffect (Image& sourceImage, - Graphics& destContext) = 0; + Graphics& destContext, + float alpha) = 0; /** Destructor. */ virtual ~ImageEffectFilter() {} @@ -26010,31 +26020,6 @@ public: */ bool isShowing() const; - /** Makes a component invisible using a groovy fade-out and animated zoom effect. - - To do this, this function will cunningly: - - take a snapshot of the component as it currently looks - - call setVisible(false) on the component - - replace it with a special component that will continue drawing the - snapshot, animating it and gradually making it more transparent - - when it's gone, the special component will also be deleted - - As soon as this method returns, the component can be safely removed and deleted - leaving the proxy to do the fade-out, so it's even ok to call this in a - component's destructor. - - Passing non-zero x and y values will cause the ghostly component image to - also whizz off by this distance while fading out. If the scale factor is - not 1.0, it will also zoom from the component's current size to this new size. - - One thing to be careful about is that the parent component must be able to cope - with this unknown component type being added to it. - */ - void fadeOutComponent (int lengthOfFadeOutInMilliseconds, - int deltaXToMove = 0, - int deltaYToMove = 0, - float scaleFactorAtEnd = 1.0f); - /** Makes this component appear as a window on the desktop. Note that before calling this, you should make sure that the component's opacity is @@ -26742,8 +26727,12 @@ public: The graphics context may be left in an undefined state after this method returns, so you may need to reset it if you're going to use it again. + + If ignoreAlphaLevel is false, then the component will be drawn with the opacity level + specified by getAlpha(); if ignoreAlphaLevel is true, then this will be ignored and + an alpha of 1.0 will be used. */ - void paintEntireComponent (Graphics& context); + void paintEntireComponent (Graphics& context, bool ignoreAlphaLevel); /** Adds an effect filter to alter the component's appearance. @@ -27046,6 +27035,9 @@ public: */ virtual void enablementChanged(); + void setAlpha (float newAlpha); + float getAlpha() const; + /** Changes the mouse cursor shape to use when the mouse is over this component. Note that the cursor set by this method can be overridden by the getMouseCursor @@ -27888,6 +27880,8 @@ private: ComponentFlags flags; }; + uint8 componentTransparency; + void internalMouseEnter (MouseInputSource& source, const Point& relativePos, const Time& time); void internalMouseExit (MouseInputSource& source, const Point& relativePos, const Time& time); void internalMouseDown (MouseInputSource& source, const Point& relativePos, const Time& time); @@ -27903,7 +27897,7 @@ private: void internalModifierKeysChanged(); void internalChildrenChanged(); void internalHierarchyChanged(); - void renderComponent (Graphics& context); + void renderComponent (Graphics& g); void sendMovedResizedMessages (bool wasMoved, bool wasResized); void repaintParent(); void sendFakeMouseMove() const; @@ -28807,6 +28801,139 @@ private: #endif // __JUCE_TIMER_JUCEHEADER__ /*** End of inlined file: juce_Timer.h ***/ + +/*** Start of inlined file: juce_ComponentAnimator.h ***/ +#ifndef __JUCE_COMPONENTANIMATOR_JUCEHEADER__ +#define __JUCE_COMPONENTANIMATOR_JUCEHEADER__ + +/** + Animates a set of components, moving them to a new position and/or fading their + alpha levels. + + To animate a component, create a ComponentAnimator instance or (preferably) use the + global animator object provided by Desktop::getAnimator(), and call its animateComponent() + method to commence the movement. + + If you're using your own ComponentAnimator instance, you'll need to make sure it isn't + deleted before it finishes moving the components, or they'll be abandoned before reaching their + destinations. + + It's ok to delete components while they're being animated - the animator will detect this + and safely stop using them. + + The class is a ChangeBroadcaster and sends a notification when any components + start or finish being animated. + + @see Desktop::getAnimator +*/ +class JUCE_API ComponentAnimator : public ChangeBroadcaster, + private Timer +{ +public: + + /** Creates a ComponentAnimator. */ + ComponentAnimator(); + + /** Destructor. */ + ~ComponentAnimator(); + + /** Starts a component moving from its current position to a specified position. + + If the component is already in the middle of an animation, that will be abandoned, + and a new animation will begin, moving the component from its current location. + + The start and end speed parameters let you apply some acceleration to the component's + movement. + + @param component the component to move + @param finalBounds the destination bounds to which the component should move. To leave the + component in the same place, just pass component->getBounds() for this value + @param finalAlpha the alpha value that the component should have at the end of the animation + @param animationDurationMilliseconds how long the animation should last, in milliseconds + @param useProxyComponent if true, this means the component should be replaced by an internally + managed temporary component which is a snapshot of the original component. + This avoids the component having to paint itself as it moves, so may + be more efficient. This option also allows you to delete the original + component immediately after starting the animation, because the animation + can proceed without it. If you use a proxy, the original component will be + made invisible by this call, and then will become visible again at the end + of the animation. It'll also mean that the proxy component will be temporarily + added to the component's parent, so avoid it if this might confuse the parent + component, or if there's a chance the parent might decide to delete its children. + @param startSpeed a value to indicate the relative start speed of the animation. If this is 0, + the component will start by accelerating from rest; higher values mean that it + will have an initial speed greater than zero. If the value if greater than 1, it + will decelerate towards the middle of its journey. To move the component at a + constant rate for its entire animation, set both the start and end speeds to 1.0 + @param endSpeed a relative speed at which the component should be moving when the animation finishes. + If this is 0, the component will decelerate to a standstill at its final position; + higher values mean the component will still be moving when it stops. To move the component + at a constant rate for its entire animation, set both the start and end speeds to 1.0 + */ + void animateComponent (Component* component, + const Rectangle& finalBounds, + float finalAlpha, + int animationDurationMilliseconds, + bool useProxyComponent, + double startSpeed, + double endSpeed); + + /** Begins a fade-out of this components alpha level. + This is a quick way of invoking animateComponent() with a target alpha value of 0.0f, using + a proxy. You're safe to delete the component after calling this method, and this won't + interfere with the animation's progress. + */ + void fadeOut (Component* component, int millisecondsToTake); + + /** Begins a fade-in of a component. + This is a quick way of invoking animateComponent() with a target alpha value of 1.0f. + */ + void fadeIn (Component* component, int millisecondsToTake); + + /** Stops a component if it's currently being animated. + + If moveComponentToItsFinalPosition is true, then the component will + be immediately moved to its destination position and size. If false, it will be + left in whatever location it currently occupies. + */ + void cancelAnimation (Component* component, + bool moveComponentToItsFinalPosition); + + /** Clears all of the active animations. + + If moveComponentsToTheirFinalPositions is true, all the components will + be immediately set to their final positions. If false, they will be + left in whatever locations they currently occupy. + */ + void cancelAllAnimations (bool moveComponentsToTheirFinalPositions); + + /** Returns the destination position for a component. + + If the component is being animated, this will return the target position that + was specified when animateComponent() was called. + + If the specified component isn't currently being animated, this method will just + return its current position. + */ + const Rectangle getComponentDestination (Component* component); + + /** Returns true if the specified component is currently being animated. */ + bool isAnimating (Component* component) const; + + juce_UseDebuggingNewOperator + +private: + class AnimationTask; + OwnedArray tasks; + uint32 lastTime; + + AnimationTask* findTaskFor (Component* component) const; + void timerCallback(); +}; + +#endif // __JUCE_COMPONENTANIMATOR_JUCEHEADER__ +/*** End of inlined file: juce_ComponentAnimator.h ***/ + class MouseInputSource; class MouseInputSourceInternal; class MouseListener; @@ -28987,6 +29114,17 @@ public: */ Component* findComponentAt (const Point& screenPosition) const; + /** The Desktop object has a ComponentAnimator instance which can be used for performing + your animations. + + Having a single shared ComponentAnimator object makes it more efficient when multiple + components are being moved around simultaneously. It's also more convenient than having + to manage your own instance of one. + + @see ComponentAnimator + */ + ComponentAnimator& getAnimator() throw() { return animator; } + /** Returns the number of MouseInputSource objects the system has at its disposal. In a traditional single-mouse system, there might be only one object. On a multi-touch system, there could be one input source per potential finger. @@ -29091,6 +29229,8 @@ private: int allowedOrientations; + ComponentAnimator animator; + void timerCallback(); void resetTimer(); @@ -42486,7 +42626,7 @@ public: juce_UseDebuggingNewOperator private: - PropertyPanel* panel; + PropertyPanel panel; GenericAudioProcessorEditor (const GenericAudioProcessorEditor&); GenericAudioProcessorEditor& operator= (const GenericAudioProcessorEditor&); @@ -43967,7 +44107,7 @@ public: int newShadowOffsetY); /** @internal */ - void applyEffect (Image& sourceImage, Graphics& destContext); + void applyEffect (Image& sourceImage, Graphics& destContext, float alpha); juce_UseDebuggingNewOperator @@ -44070,12 +44210,8 @@ public: RelativeCoordinate (double absoluteDistanceFromOrigin); /** Recreates a coordinate from a string description. - The string will be parsed by ExpressionParser::parse(). - @param stringVersion the expression to use - @param isHorizontal this must be true if this is an X coordinate, or false if it's on the Y axis. - @see toString */ RelativeCoordinate (const String& stringVersion); @@ -45501,115 +45637,6 @@ private: #endif // __JUCE_DRAGANDDROPCONTAINER_JUCEHEADER__ /*** End of inlined file: juce_DragAndDropContainer.h ***/ - -/*** Start of inlined file: juce_ComponentAnimator.h ***/ -#ifndef __JUCE_COMPONENTANIMATOR_JUCEHEADER__ -#define __JUCE_COMPONENTANIMATOR_JUCEHEADER__ - -/** - Animates a set of components, moving it to a new position. - - To use this, create a ComponentAnimator, and use its animateComponent() method - to tell it to move components to destination positions. Any number of - components can be animated by one ComponentAnimator object (if you've got a - lot of components to move, it's much more efficient to share a single animator - than to have many animators running at once). - - You'll need to make sure the animator object isn't deleted before it finishes - moving the components. - - The class is a ChangeBroadcaster and sends a notification when any components - start or finish being animated. -*/ -class JUCE_API ComponentAnimator : public ChangeBroadcaster, - private Timer -{ -public: - - /** Creates a ComponentAnimator. */ - ComponentAnimator(); - - /** Destructor. */ - ~ComponentAnimator(); - - /** Starts a component moving from its current position to a specified position. - - If the component is already in the middle of an animation, that will be abandoned, - and a new animation will begin, moving the component from its current location. - - The start and end speed parameters let you apply some acceleration to the component's - movement. - - @param component the component to move - @param finalPosition the destination position and size to move it to - @param millisecondsToSpendMoving how long, in milliseconds, it should take - to arrive at its destination - @param startSpeed a value to indicate the relative start speed of the - animation. If this is 0, the component will start - by accelerating from rest; higher values mean that it - will have an initial speed greater than zero. If the - value if greater than 1, it will decelerate towards the - middle of its journey. To move the component at a constant - rate for its entire animation, set both the start and - end speeds to 1.0 - @param endSpeed a relative speed at which the component should be moving - when the animation finishes. If this is 0, the component - will decelerate to a standstill at its final position; higher - values mean the component will still be moving when it stops. - To move the component at a constant rate for its entire - animation, set both the start and end speeds to 1.0 - */ - void animateComponent (Component* component, - const Rectangle& finalPosition, - int millisecondsToSpendMoving, - double startSpeed = 1.0, - double endSpeed = 1.0); - - /** Stops a component if it's currently being animated. - - If moveComponentToItsFinalPosition is true, then the component will - be immediately moved to its destination position and size. If false, it will be - left in whatever location it currently occupies. - */ - void cancelAnimation (Component* component, - bool moveComponentToItsFinalPosition); - - /** Clears all of the active animations. - - If moveComponentsToTheirFinalPositions is true, all the components will - be immediately set to their final positions. If false, they will be - left in whatever locations they currently occupy. - */ - void cancelAllAnimations (bool moveComponentsToTheirFinalPositions); - - /** Returns the destination position for a component. - - If the component is being animated, this will return the target position that - was specified when animateComponent() was called. - - If the specified component isn't currently being animated, this method will just - return its current position. - */ - const Rectangle getComponentDestination (Component* component); - - /** Returns true if the specified component is currently being animated. - */ - bool isAnimating (Component* component) const; - - juce_UseDebuggingNewOperator - -private: - class AnimationTask; - OwnedArray tasks; - uint32 lastTime; - - AnimationTask* findTaskFor (Component* component) const; - void timerCallback(); -}; - -#endif // __JUCE_COMPONENTANIMATOR_JUCEHEADER__ -/*** End of inlined file: juce_ComponentAnimator.h ***/ - class ToolbarItemComponent; class ToolbarItemFactory; @@ -45869,7 +45896,6 @@ private: Button* missingItemsButton; bool vertical, isEditingActive; ToolbarItemStyle toolbarStyle; - ComponentAnimator animator; class MissingItemsComponent; friend class MissingItemsComponent; Array items; @@ -52521,13 +52547,14 @@ public: private: - KeyPressMappingSet* mappings; - TreeView* tree; friend class KeyMappingTreeViewItem; friend class KeyCategoryTreeViewItem; friend class KeyMappingItemComponent; friend class KeyMappingChangeButton; - TextButton* resetButton; + + KeyPressMappingSet* mappings; + TreeView tree; + TextButton resetButton; void assignNewKey (CommandID commandID, int index); @@ -56770,7 +56797,7 @@ public: juce_UseDebuggingNewOperator private: - Label* textEditor; + ScopedPointer