diff --git a/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.cpp b/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.cpp index 3b077e1e08..8c6578bcff 100644 --- a/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.cpp +++ b/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.cpp @@ -897,12 +897,7 @@ void AudioProcessorGraph::Node::prepare (const double sampleRate, const int bloc if (! isPrepared) { isPrepared = true; - - AudioProcessorGraph::AudioGraphIOProcessor* const ioProc - = dynamic_cast (static_cast (processor)); - - if (ioProc != nullptr) - ioProc->setParentGraph (graph); + setParentGraph (graph); processor->setPlayConfigDetails (processor->getNumInputChannels(), processor->getNumOutputChannels(), @@ -921,6 +916,15 @@ void AudioProcessorGraph::Node::unprepare() } } +void AudioProcessorGraph::Node::setParentGraph (AudioProcessorGraph* const graph) const +{ + AudioProcessorGraph::AudioGraphIOProcessor* const ioProc + = dynamic_cast (processor.get()); + + if (ioProc != nullptr) + ioProc->setParentGraph (graph); +} + //============================================================================== AudioProcessorGraph::AudioProcessorGraph() : lastNodeId (0), @@ -983,12 +987,7 @@ AudioProcessorGraph::Node* AudioProcessorGraph::addNode (AudioProcessor* const n nodes.add (n); triggerAsyncUpdate(); - AudioProcessorGraph::AudioGraphIOProcessor* const ioProc - = dynamic_cast (static_cast (n->processor)); - - if (ioProc != nullptr) - ioProc->setParentGraph (this); - + n->setParentGraph (this); return n; } @@ -1000,12 +999,7 @@ bool AudioProcessorGraph::removeNode (const uint32 nodeId) { if (nodes.getUnchecked(i)->nodeId == nodeId) { - AudioProcessorGraph::AudioGraphIOProcessor* const ioProc - = dynamic_cast (static_cast (nodes.getUnchecked(i)->processor)); - - if (ioProc != nullptr) - ioProc->setParentGraph (nullptr); - + nodes.getUnchecked(i)->setParentGraph (nullptr); nodes.remove (i); triggerAsyncUpdate(); diff --git a/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.h b/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.h index fd39979054..b224c2fc10 100644 --- a/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.h +++ b/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.h @@ -97,6 +97,7 @@ public: Node (uint32 nodeId, AudioProcessor*) noexcept; + void setParentGraph (AudioProcessorGraph*) const; void prepare (double sampleRate, int blockSize, AudioProcessorGraph*); void unprepare(); diff --git a/modules/juce_audio_utils/gui/juce_AudioDeviceSelectorComponent.cpp b/modules/juce_audio_utils/gui/juce_AudioDeviceSelectorComponent.cpp index 51418a21a9..09ca9c0c10 100644 --- a/modules/juce_audio_utils/gui/juce_AudioDeviceSelectorComponent.cpp +++ b/modules/juce_audio_utils/gui/juce_AudioDeviceSelectorComponent.cpp @@ -497,7 +497,7 @@ private: { if (box != nullptr) { - AudioIODevice* const currentDevice = dynamic_cast (setup.manager->getCurrentAudioDevice()); + AudioIODevice* const currentDevice = setup.manager->getCurrentAudioDevice(); const int index = type->getIndexOfDevice (currentDevice, isInput); diff --git a/modules/juce_core/json/juce_JSON.cpp b/modules/juce_core/json/juce_JSON.cpp index 1185f0f606..e805c3abc2 100644 --- a/modules/juce_core/json/juce_JSON.cpp +++ b/modules/juce_core/json/juce_JSON.cpp @@ -329,7 +329,7 @@ public: } else if (v.isObject()) { - DynamicObject* object = dynamic_cast (v.getObject()); + DynamicObject* const object = v.getDynamicObject(); jassert (object != nullptr); // Only DynamicObjects can be converted to JSON! diff --git a/modules/juce_core/maths/juce_Expression.cpp b/modules/juce_core/maths/juce_Expression.cpp index 819be9de28..fc96184983 100644 --- a/modules/juce_core/maths/juce_Expression.cpp +++ b/modules/juce_core/maths/juce_Expression.cpp @@ -574,25 +574,34 @@ struct Expression::Helpers static Constant* findTermToAdjust (Term* const term, const bool mustBeFlagged) { + jassert (term != nullptr); + + if (term->getType() == constantType) { - Constant* const c = dynamic_cast (term); - if (c != nullptr && (c->isResolutionTarget || ! mustBeFlagged)) + Constant* const c = static_cast (term); + if (c->isResolutionTarget || ! mustBeFlagged) return c; } - if (dynamic_cast (term) != nullptr) + if (term->getType() == functionType) return nullptr; - int i; const int numIns = term->getNumInputs(); - for (i = 0; i < numIns; ++i) + + for (int i = 0; i < numIns; ++i) { - Constant* const c = dynamic_cast (term->getInput (i)); - if (c != nullptr && (c->isResolutionTarget || ! mustBeFlagged)) - return c; + Term* const input = term->getInput (i); + + if (input->getType() == constantType) + { + Constant* const c = static_cast (input); + + if (c->isResolutionTarget || ! mustBeFlagged) + return c; + } } - for (i = 0; i < numIns; ++i) + for (int i = 0; i < numIns; ++i) { Constant* const c = findTermToAdjust (term->getInput (i), mustBeFlagged); if (c != nullptr) diff --git a/modules/juce_core/native/juce_android_JNIHelpers.h b/modules/juce_core/native/juce_android_JNIHelpers.h index e5f8578626..c9af6c52cd 100644 --- a/modules/juce_core/native/juce_android_JNIHelpers.h +++ b/modules/juce_core/native/juce_android_JNIHelpers.h @@ -26,10 +26,6 @@ #ifndef __JUCE_ANDROID_JNIHELPERS_JUCEHEADER__ #define __JUCE_ANDROID_JNIHELPERS_JUCEHEADER__ -#ifndef USE_ANDROID_CANVAS - #define USE_ANDROID_CANVAS 0 -#endif - #if ! (defined (JUCE_ANDROID_ACTIVITY_CLASSNAME) && defined (JUCE_ANDROID_ACTIVITY_CLASSPATH)) #error "The JUCE_ANDROID_ACTIVITY_CLASSNAME and JUCE_ANDROID_ACTIVITY_CLASSPATH macros must be set!" #endif diff --git a/modules/juce_events/broadcasters/juce_ActionBroadcaster.cpp b/modules/juce_events/broadcasters/juce_ActionBroadcaster.cpp index ea7f9aab8c..7b874c8ca1 100644 --- a/modules/juce_events/broadcasters/juce_ActionBroadcaster.cpp +++ b/modules/juce_events/broadcasters/juce_ActionBroadcaster.cpp @@ -23,45 +23,46 @@ ============================================================================== */ -class ActionMessage : public Message +class ActionBroadcaster::ActionMessage : public MessageManager::MessageBase { public: - ActionMessage (const String& messageText, ActionListener* const listener_) noexcept - : message (messageText), + ActionMessage (const ActionBroadcaster* const broadcaster_, + const String& messageText, + ActionListener* const listener_) noexcept + : broadcaster (const_cast (broadcaster_)), + message (messageText), listener (listener_) + {} + + void messageCallback() { + const ActionBroadcaster* const b = broadcaster; + + if (b != nullptr && b->actionListeners.contains (listener)) + listener->actionListenerCallback (message); } +private: + WeakReference broadcaster; const String message; ActionListener* const listener; -private: JUCE_DECLARE_NON_COPYABLE (ActionMessage); }; -ActionBroadcaster::CallbackReceiver::CallbackReceiver() {} - -void ActionBroadcaster::CallbackReceiver::handleMessage (const Message& message) -{ - const ActionMessage& am = static_cast (message); - - if (owner->actionListeners.contains (am.listener)) - am.listener->actionListenerCallback (am.message); -} - //============================================================================== ActionBroadcaster::ActionBroadcaster() { // are you trying to create this object before or after juce has been intialised?? jassert (MessageManager::getInstanceWithoutCreating() != nullptr); - - callback.owner = this; } ActionBroadcaster::~ActionBroadcaster() { // all event-based objects must be deleted BEFORE juce is shut down! jassert (MessageManager::getInstanceWithoutCreating() != nullptr); + + masterReference.clear(); } void ActionBroadcaster::addActionListener (ActionListener* const listener) @@ -89,5 +90,5 @@ void ActionBroadcaster::sendActionMessage (const String& message) const const ScopedLock sl (actionListenerLock); for (int i = actionListeners.size(); --i >= 0;) - callback.postMessage (new ActionMessage (message, actionListeners.getUnchecked(i))); + (new ActionMessage (this, message, actionListeners.getUnchecked(i)))->post(); } diff --git a/modules/juce_events/broadcasters/juce_ActionBroadcaster.h b/modules/juce_events/broadcasters/juce_ActionBroadcaster.h index ecfd8cfe0e..01248a862a 100644 --- a/modules/juce_events/broadcasters/juce_ActionBroadcaster.h +++ b/modules/juce_events/broadcasters/juce_ActionBroadcaster.h @@ -27,7 +27,6 @@ #define __JUCE_ACTIONBROADCASTER_JUCEHEADER__ #include "juce_ActionListener.h" -#include "../messages/juce_MessageListener.h" //============================================================================== @@ -71,17 +70,12 @@ public: private: //============================================================================== - class CallbackReceiver : public MessageListener - { - public: - CallbackReceiver(); - void handleMessage (const Message&); + friend class WeakReference; + WeakReference::Master masterReference; - ActionBroadcaster* owner; - }; + class ActionMessage; + friend class ActionMessage; - friend class CallbackReceiver; - CallbackReceiver callback; SortedSet actionListeners; CriticalSection actionListenerLock; diff --git a/modules/juce_events/interprocess/juce_InterprocessConnection.cpp b/modules/juce_events/interprocess/juce_InterprocessConnection.cpp index cb16d2b113..a2619f4706 100644 --- a/modules/juce_events/interprocess/juce_InterprocessConnection.cpp +++ b/modules/juce_events/interprocess/juce_InterprocessConnection.cpp @@ -37,6 +37,7 @@ InterprocessConnection::~InterprocessConnection() { callbackConnectionState = false; disconnect(); + masterReference.clear(); } @@ -188,44 +189,28 @@ void InterprocessConnection::initialiseWithPipe (NamedPipe* const pipe_) } //============================================================================== -struct ConnectionStateMessage : public Message +struct ConnectionStateMessage : public MessageManager::MessageBase { - ConnectionStateMessage (bool connectionMade_) noexcept - : connectionMade (connectionMade_) + ConnectionStateMessage (InterprocessConnection* owner_, bool connectionMade_) noexcept + : owner (owner_), connectionMade (connectionMade_) {} + void messageCallback() + { + InterprocessConnection* const ipc = owner; + if (ipc != nullptr) + { + if (connectionMade) + ipc->connectionMade(); + else + ipc->connectionLost(); + } + } + + WeakReference owner; bool connectionMade; }; -struct DataDeliveryMessage : public Message -{ - DataDeliveryMessage (const MemoryBlock& data_) - : data (data_) - {} - - MemoryBlock data; -}; - -void InterprocessConnection::handleMessage (const Message& message) -{ - const ConnectionStateMessage* m = dynamic_cast (&message); - - if (m != nullptr) - { - if (m->connectionMade) - connectionMade(); - else - connectionLost(); - } - else - { - const DataDeliveryMessage* d = dynamic_cast (&message); - - if (d != nullptr) - messageReceived (d->data); - } -} - void InterprocessConnection::connectionMadeInt() { if (! callbackConnectionState) @@ -233,7 +218,7 @@ void InterprocessConnection::connectionMadeInt() callbackConnectionState = true; if (useMessageThread) - postMessage (new ConnectionStateMessage (true)); + (new ConnectionStateMessage (this, true))->post(); else connectionMade(); } @@ -246,18 +231,35 @@ void InterprocessConnection::connectionLostInt() callbackConnectionState = false; if (useMessageThread) - postMessage (new ConnectionStateMessage (false)); + (new ConnectionStateMessage (this, false))->post(); else connectionLost(); } } +struct DataDeliveryMessage : public Message +{ + DataDeliveryMessage (InterprocessConnection* owner_, const MemoryBlock& data_) + : owner (owner_), data (data_) + {} + + void messageCallback() + { + InterprocessConnection* const ipc = owner; + if (ipc != nullptr) + ipc->messageReceived (data); + } + + WeakReference owner; + MemoryBlock data; +}; + void InterprocessConnection::deliverDataInt (const MemoryBlock& data) { jassert (callbackConnectionState); if (useMessageThread) - postMessage (new DataDeliveryMessage (data)); + (new DataDeliveryMessage (this, data))->post(); else messageReceived (data); } diff --git a/modules/juce_events/interprocess/juce_InterprocessConnection.h b/modules/juce_events/interprocess/juce_InterprocessConnection.h index 60d87b6fe9..63794c8e61 100644 --- a/modules/juce_events/interprocess/juce_InterprocessConnection.h +++ b/modules/juce_events/interprocess/juce_InterprocessConnection.h @@ -26,7 +26,6 @@ #ifndef __JUCE_INTERPROCESSCONNECTION_JUCEHEADER__ #define __JUCE_INTERPROCESSCONNECTION_JUCEHEADER__ -#include "../messages/juce_MessageListener.h" class InterprocessConnectionServer; class MemoryBlock; @@ -49,8 +48,7 @@ class MemoryBlock; @see InterprocessConnectionServer, Socket, NamedPipe */ -class JUCE_API InterprocessConnection : public Thread, - private MessageListener +class JUCE_API InterprocessConnection : public Thread { public: //============================================================================== @@ -181,6 +179,8 @@ public: private: //============================================================================== + WeakReference::Master masterReference; + friend class WeakReference; CriticalSection pipeAndSocketLock; ScopedPointer socket; ScopedPointer pipe; @@ -189,12 +189,9 @@ private: const uint32 magicMessageHeader; int pipeReceiveMessageTimeout; - //============================================================================== friend class InterprocessConnectionServer; - void initialiseWithSocket (StreamingSocket*); void initialiseWithPipe (NamedPipe*); - void handleMessage (const Message&); void connectionMadeInt(); void connectionLostInt(); void deliverDataInt (const MemoryBlock&); diff --git a/modules/juce_events/messages/juce_ApplicationBase.h b/modules/juce_events/messages/juce_ApplicationBase.h index c13f4d4a3f..aa8fe11040 100644 --- a/modules/juce_events/messages/juce_ApplicationBase.h +++ b/modules/juce_events/messages/juce_ApplicationBase.h @@ -133,14 +133,14 @@ public: passed-in will be valid. If the exception is of unknown type, this pointer will be null. */ - virtual void unhandledException (const std::exception* e, + virtual void unhandledException (const std::exception*, const String& sourceFilename, int lineNumber) = 0; //============================================================================== /** Returns true if this executable is running as an app (as opposed to being a plugin or other kind of shared library. */ - static inline bool isStandaloneApp() noexcept { return createInstance != 0; } + static inline bool isStandaloneApp() noexcept { return createInstance != nullptr; } //============================================================================== #ifndef DOXYGEN diff --git a/modules/juce_events/timers/juce_Timer.cpp b/modules/juce_events/timers/juce_Timer.cpp index 6ad097ce00..1c99c75bd1 100644 --- a/modules/juce_events/timers/juce_Timer.cpp +++ b/modules/juce_events/timers/juce_Timer.cpp @@ -24,7 +24,6 @@ */ class Timer::TimerThread : private Thread, - private MessageListener, private DeletedAtShutdown, private AsyncUpdater { @@ -51,7 +50,7 @@ public: void run() { uint32 lastTime = Time::getMillisecondCounter(); - Message::Ptr messageToSend (new Message()); + MessageManager::MessageBase::Ptr messageToSend (new CallTimersMessage()); while (! threadShouldExit()) { @@ -78,7 +77,7 @@ public: */ if (callbackNeeded.compareAndSetBool (1, 0)) { - postMessage (messageToSend); + messageToSend->post(); /* Sometimes our message can get discarded by the OS (e.g. when running as an RTAS when the app has a modal loop), so this is how long to wait before assuming the @@ -137,11 +136,6 @@ public: callbackNeeded.set (0); } - void handleMessage (const Message&) - { - callTimers(); - } - void callTimersSynchronously() { if (! isThreadRunning()) @@ -192,6 +186,17 @@ private: Timer* volatile firstTimer; Atomic callbackNeeded; + struct CallTimersMessage : public MessageManager::MessageBase + { + CallTimersMessage() {} + + void messageCallback() + { + if (instance != nullptr) + instance->callTimers(); + } + }; + //============================================================================== void addTimer (Timer* const t) noexcept { diff --git a/modules/juce_graphics/native/juce_android_GraphicsContext.cpp b/modules/juce_graphics/native/juce_android_GraphicsContext.cpp index 95f7233350..0793958b98 100644 --- a/modules/juce_graphics/native/juce_android_GraphicsContext.cpp +++ b/modules/juce_graphics/native/juce_android_GraphicsContext.cpp @@ -55,877 +55,7 @@ namespace GraphicsHelpers } } -#if USE_ANDROID_CANVAS - -//============================================================================== -#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ - METHOD (constructor, "", "(Landroid/graphics/Bitmap;)V") \ - METHOD (drawRect, "drawRect", "(FFFFLandroid/graphics/Paint;)V") \ - METHOD (translate, "translate", "(FF)V") \ - METHOD (clipPath, "clipPath", "(Landroid/graphics/Path;)Z") \ - METHOD (clipRect, "clipRect", "(FFFF)Z") \ - METHOD (clipRegion, "clipRegion", "(Landroid/graphics/Region;)Z") \ - METHOD (concat, "concat", "(Landroid/graphics/Matrix;)V") \ - METHOD (drawBitmap, "drawBitmap", "(Landroid/graphics/Bitmap;Landroid/graphics/Matrix;Landroid/graphics/Paint;)V") \ - METHOD (drawBitmapAt, "drawBitmap", "(Landroid/graphics/Bitmap;FFLandroid/graphics/Paint;)V") \ - METHOD (drawMemoryBitmap, "drawBitmap", "([IIIFFIIZLandroid/graphics/Paint;)V") \ - METHOD (drawLine, "drawLine", "(FFFFLandroid/graphics/Paint;)V") \ - METHOD (drawPath, "drawPath", "(Landroid/graphics/Path;Landroid/graphics/Paint;)V") \ - METHOD (drawText, "drawText", "(Ljava/lang/String;FFLandroid/graphics/Paint;)V") \ - METHOD (getClipBounds, "getClipBounds", "(Landroid/graphics/Rect;)Z") \ - METHOD (getClipBounds2, "getClipBounds", "()Landroid/graphics/Rect;") \ - METHOD (getMatrix, "getMatrix", "()Landroid/graphics/Matrix;") \ - METHOD (save, "save", "()I") \ - METHOD (restore, "restore", "()V") \ - METHOD (saveLayerAlpha, "saveLayerAlpha", "(FFFFII)I") - -DECLARE_JNI_CLASS (Canvas, "android/graphics/Canvas"); -#undef JNI_CLASS_MEMBERS - -//============================================================================== -#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ - METHOD (constructor, "", "()V") \ - METHOD (moveTo, "moveTo", "(FF)V") \ - METHOD (lineTo, "lineTo", "(FF)V") \ - METHOD (quadTo, "quadTo", "(FFFF)V") \ - METHOD (cubicTo, "cubicTo", "(FFFFFF)V") \ - METHOD (closePath, "close", "()V") \ - METHOD (computeBounds, "computeBounds", "(Landroid/graphics/RectF;Z)V") \ - -DECLARE_JNI_CLASS (PathClass, "android/graphics/Path"); -#undef JNI_CLASS_MEMBERS - -//============================================================================== -#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ - METHOD (constructor, "", "()V"); \ - METHOD (regionUnion, "union", "(Landroid/graphics/Rect;)Z"); \ - -DECLARE_JNI_CLASS (RegionClass, "android/graphics/Region"); -#undef JNI_CLASS_MEMBERS - -//============================================================================== -#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ - STATICMETHOD (createBitmap, "createBitmap", "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;") \ - METHOD (bitmapCopy, "copy", "(Landroid/graphics/Bitmap$Config;Z)Landroid/graphics/Bitmap;") \ - METHOD (getPixels, "getPixels", "([IIIIIII)V") \ - METHOD (setPixels, "setPixels", "([IIIIIII)V") \ - METHOD (recycle, "recycle", "()V") \ - -DECLARE_JNI_CLASS (BitmapClass, "android/graphics/Bitmap"); -#undef JNI_CLASS_MEMBERS - -//============================================================================== -#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ - STATICFIELD (ARGB_8888, "ARGB_8888", "Landroid/graphics/Bitmap$Config;") \ - STATICFIELD (ALPHA_8, "ALPHA_8", "Landroid/graphics/Bitmap$Config;") \ - -DECLARE_JNI_CLASS (BitmapConfig, "android/graphics/Bitmap$Config"); -#undef JNI_CLASS_MEMBERS - -//============================================================================== -#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ - METHOD (constructor, "", "(Landroid/graphics/Bitmap;Landroid/graphics/Shader$TileMode;Landroid/graphics/Shader$TileMode;)V") - -DECLARE_JNI_CLASS (BitmapShader, "android/graphics/BitmapShader"); -#undef JNI_CLASS_MEMBERS - -//============================================================================== -#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ - METHOD (setLocalMatrix, "setLocalMatrix", "(Landroid/graphics/Matrix;)V") - -DECLARE_JNI_CLASS (ShaderClass, "android/graphics/Shader"); -#undef JNI_CLASS_MEMBERS - -//============================================================================== -#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ - STATICFIELD (CLAMP, "CLAMP", "Landroid/graphics/Shader$TileMode;") - -DECLARE_JNI_CLASS (ShaderTileMode, "android/graphics/Shader$TileMode"); -#undef JNI_CLASS_MEMBERS - -//============================================================================== -#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ - METHOD (constructor, "", "(FFFF[I[FLandroid/graphics/Shader$TileMode;)V") \ - -DECLARE_JNI_CLASS (LinearGradientClass, "android/graphics/LinearGradient"); -#undef JNI_CLASS_MEMBERS - -//============================================================================== -#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ - METHOD (constructor, "", "(FFF[I[FLandroid/graphics/Shader$TileMode;)V") \ - -DECLARE_JNI_CLASS (RadialGradientClass, "android/graphics/RadialGradient"); -#undef JNI_CLASS_MEMBERS - -//============================================================================== -class AndroidImage : public ImagePixelData -{ -public: - AndroidImage (const int width_, const int height_, const bool clearImage) - : ImagePixelData (Image::ARGB, width_, height_), - bitmap (createBitmap (width_, height_, false)) - { - } - - AndroidImage (const int width_, const int height_, const GlobalRef& bitmap_) - : ImagePixelData (Image::ARGB, width_, height_), - bitmap (bitmap_) - { - } - - ~AndroidImage() - { - if (bitmap != 0) - bitmap.callVoidMethod (BitmapClass.recycle); - } - - LowLevelGraphicsContext* createLowLevelContext(); - - void initialiseBitmapData (Image::BitmapData& bm, int x, int y, Image::BitmapData::ReadWriteMode mode) - { - bm.lineStride = width * sizeof (jint); - bm.pixelStride = sizeof (jint); - bm.pixelFormat = Image::ARGB; - bm.dataReleaser = new CopyHandler (*this, bm, x, y, mode); - } - - ImagePixelData* clone() - { - JNIEnv* env = getEnv(); - jobject mode = env->GetStaticObjectField (BitmapConfig, BitmapConfig.ARGB_8888); - GlobalRef newCopy (bitmap.callObjectMethod (BitmapClass.bitmapCopy, mode, true)); - env->DeleteLocalRef (mode); - - return new AndroidImage (width, height, newCopy); - } - - ImageType* createType() const { return new NativeImageType(); } - - static jobject createBitmap (int width, int height, bool asSingleChannel) - { - JNIEnv* env = getEnv(); - jobject mode = env->GetStaticObjectField (BitmapConfig, asSingleChannel ? BitmapConfig.ALPHA_8 - : BitmapConfig.ARGB_8888); - jobject result = env->CallStaticObjectMethod (BitmapClass, BitmapClass.createBitmap, width, height, mode); - env->DeleteLocalRef (mode); - return result; - } - - //============================================================================== - GlobalRef bitmap; - -private: - class CopyHandler : public Image::BitmapData::BitmapDataReleaser - { - public: - CopyHandler (AndroidImage& owner_, Image::BitmapData& bitmapData_, - const int x_, const int y_, const Image::BitmapData::ReadWriteMode mode_) - : owner (owner_), bitmapData (bitmapData_), mode (mode_), x (x_), y (y_) - { - JNIEnv* env = getEnv(); - - intArray = env->NewIntArray (bitmapData.width * bitmapData.height); - - if (mode != Image::BitmapData::writeOnly) - owner_.bitmap.callVoidMethod (BitmapClass.getPixels, intArray, 0, bitmapData.width, x_, y_, - bitmapData.width, bitmapData.height); - - bitmapData.data = (uint8*) env->GetIntArrayElements (intArray, 0); - - if (mode != Image::BitmapData::writeOnly) - { - for (int yy = 0; yy < bitmapData.height; ++yy) - { - PixelARGB* p = (PixelARGB*) bitmapData.getLinePointer (yy); - - for (int xx = 0; xx < bitmapData.width; ++xx) - p[xx].premultiply(); - } - } - } - - ~CopyHandler() - { - JNIEnv* env = getEnv(); - - if (mode != Image::BitmapData::readOnly) - { - for (int yy = 0; yy < bitmapData.height; ++yy) - { - PixelARGB* p = (PixelARGB*) bitmapData.getLinePointer (yy); - - for (int xx = 0; xx < bitmapData.width; ++xx) - p[xx].unpremultiply(); - } - } - - env->ReleaseIntArrayElements (intArray, (jint*) bitmapData.data, 0); - - if (mode != Image::BitmapData::readOnly) - owner.bitmap.callVoidMethod (BitmapClass.setPixels, intArray, 0, bitmapData.width, x, y, - bitmapData.width, bitmapData.height); - - env->DeleteLocalRef (intArray); - } - - private: - AndroidImage& owner; - Image::BitmapData& bitmapData; - jintArray intArray; - const Image::BitmapData::ReadWriteMode mode; - const int x, y; - - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CopyHandler); - }; - - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AndroidImage); -}; -#endif - ImagePixelData* NativeImageType::create (Image::PixelFormat format, int width, int height, bool clearImage) const { - #if USE_ANDROID_CANVAS - if (pixelFormat != Image::SingleChannel) - return new AndroidImage (width, height, clearImage); - #endif - return SoftwareImageType().create (format, width, height, clearImage); } - -#if USE_ANDROID_CANVAS -//============================================================================== -class AndroidLowLevelGraphicsContext : public LowLevelGraphicsContext -{ -public: - AndroidLowLevelGraphicsContext (jobject canvas_) - : originalCanvas (canvas_), - currentState (new SavedState (canvas_)) - { - setFill (Colours::black); - } - - ~AndroidLowLevelGraphicsContext() - { - while (stateStack.size() > 0) - restoreState(); - - currentState->flattenImageClippingLayer (originalCanvas); - } - - bool isVectorDevice() const { return false; } - - //============================================================================== - void setOrigin (int x, int y) - { - getCanvas().callVoidMethod (Canvas.translate, (float) x, (float) y); - } - - void addTransform (const AffineTransform& transform) - { - getCanvas().callVoidMethod (Canvas.concat, createMatrixRef (getEnv(), transform).get()); - } - - float getScaleFactor() - { - return 1.0f; - } - - bool clipToRectangle (const Rectangle& r) - { - return getCanvas().callBooleanMethod (Canvas.clipRect, (float) r.getX(), (float) r.getY(), (float) r.getRight(), (float) r.getBottom()); - } - - bool clipToRectangleList (const RectangleList& clipRegion) - { - RectangleList excluded (getClipBounds()); - excluded.subtract (clipRegion); - - const int numRects = excluded.getNumRectangles(); - - for (int i = 0; i < numRects; ++i) - excludeClipRectangle (excluded.getRectangle(i)); - } - - void excludeClipRectangle (const Rectangle& r) - { - android.activity.callVoidMethod (JuceAppActivity.excludeClipRegion, getCanvas().get(), - (float) r.getX(), (float) r.getY(), (float) r.getRight(), (float) r.getBottom()); - } - - void clipToPath (const Path& path, const AffineTransform& transform) - { - (void) getCanvas().callBooleanMethod (Canvas.clipPath, createPath (getEnv(), path, transform).get()); - } - - void clipToImageAlpha (const Image& sourceImage, const AffineTransform& transform) - { - // XXX couldn't get image clipping to work... - JNIEnv* env = getEnv(); - - { - Path p; - p.addRectangle (sourceImage.getBounds().toFloat()); - clipToPath (p, transform); - } - - Rectangle bounds (getClipBounds()); - - jobject temporaryLayerBitmap = AndroidImage::createBitmap (bounds.getWidth(), bounds.getHeight(), false); - jobject temporaryCanvas = env->NewObject (Canvas, Canvas.constructor, temporaryLayerBitmap); - - setFill (Colours::red); - env->CallVoidMethod (temporaryCanvas, Canvas.drawRect, - (jfloat) 20, (jfloat) 20, (jfloat) 300, (jfloat) 200, - getCurrentPaint()); - - env->CallVoidMethod (temporaryCanvas, Canvas.translate, - (jfloat) -bounds.getX(), (jfloat) -bounds.getY()); - - Image maskImage (Image::SingleChannel, bounds.getWidth(), bounds.getHeight(), true); - - { - Graphics g (maskImage); - g.setOrigin (-bounds.getWidth(), -bounds.getHeight()); - g.drawImageTransformed (sourceImage, transform); - } - - SavedState* const top = stateStack.getLast(); - currentState->clipToImage (top != nullptr ? top->canvas.get() : originalCanvas, - temporaryCanvas, temporaryLayerBitmap, maskImage, - bounds.getX(), bounds.getY()); - } - - bool clipRegionIntersects (const Rectangle& r) - { - return getClipBounds().intersects (r); - } - - Rectangle getClipBounds() const - { - JNIEnv* env = getEnv(); - jobject rect = getCanvas().callObjectMethod (Canvas.getClipBounds2); - - const int left = env->GetIntField (rect, RectClass.left); - const int top = env->GetIntField (rect, RectClass.top); - const int right = env->GetIntField (rect, RectClass.right); - const int bottom = env->GetIntField (rect, RectClass.bottom); - env->DeleteLocalRef (rect); - - return Rectangle::leftTopRightBottom (left, top, right, bottom); - } - - bool isClipEmpty() const - { - LocalRef tempRect (getEnv()->NewObject (RectClass, RectClass.constructor, 0, 0, 0, 0)); - return ! getCanvas().callBooleanMethod (Canvas.getClipBounds, tempRect.get()); - } - - //============================================================================== - void setFill (const FillType& fillType) - { - currentState->setFillType (fillType); - } - - void setOpacity (float newOpacity) - { - currentState->setAlpha (newOpacity); - } - - void setInterpolationQuality (Graphics::ResamplingQuality quality) - { - currentState->setInterpolationQuality (quality); - } - - //============================================================================== - void fillRect (const Rectangle& r, bool replaceExistingContents) - { - getCanvas().callVoidMethod (Canvas.drawRect, - (float) r.getX(), (float) r.getY(), (float) r.getRight(), (float) r.getBottom(), - getCurrentPaint()); - } - - void fillPath (const Path& path, const AffineTransform& transform) - { - getCanvas().callVoidMethod (Canvas.drawPath, createPath (getEnv(), path, transform).get(), - getCurrentPaint()); - } - - void drawImage (const Image& sourceImage, const AffineTransform& transform) - { - AndroidImage* androidImage = dynamic_cast (sourceImage.getPixelData()); - - if (androidImage != 0) - { - JNIEnv* env = getEnv(); - getCanvas().callVoidMethod (Canvas.drawBitmap, androidImage->bitmap.get(), - createMatrixRef (env, transform).get(), getImagePaint()); - } - else - { - if (transform.isOnlyTranslation()) - { - JNIEnv* env = getEnv(); - - Image::BitmapData bm (sourceImage, Image::BitmapData::readOnly); - - jintArray imageData = env->NewIntArray (bm.width * bm.height); - jint* dest = env->GetIntArrayElements (imageData, 0); - - if (dest != 0) - { - const uint8* srcLine = bm.getLinePointer (0); - jint* dstLine = dest; - - for (int y = 0; y < bm.height; ++y) - { - switch (bm.pixelFormat) - { - case Image::ARGB: copyPixels (dstLine, (PixelARGB*) srcLine, bm.width, bm.pixelStride); break; - case Image::RGB: copyPixels (dstLine, (PixelRGB*) srcLine, bm.width, bm.pixelStride); break; - case Image::SingleChannel: copyPixels (dstLine, (PixelAlpha*) srcLine, bm.width, bm.pixelStride); break; - default: jassertfalse; break; - } - - srcLine += bm.lineStride; - dstLine += bm.width; - } - - env->ReleaseIntArrayElements (imageData, dest, 0); - - getCanvas().callVoidMethod (Canvas.drawMemoryBitmap, imageData, 0, bm.width, - transform.getTranslationX(), transform.getTranslationY(), - bm.width, bm.height, true, getImagePaint()); - env->DeleteLocalRef (imageData); - } - } - else - { - saveState(); - addTransform (transform); - drawImage (sourceImage, AffineTransform::identity); - restoreState(); - } - } - } - - void drawLine (const Line & line) - { - getCanvas().callVoidMethod (Canvas.drawLine, line.getStartX(), line.getStartY(), - line.getEndX(), line.getEndY(), getCurrentPaint()); - } - - void drawVerticalLine (int x, float top, float bottom) - { - getCanvas().callVoidMethod (Canvas.drawRect, (float) x, top, x + 1.0f, bottom, getCurrentPaint()); - } - - void drawHorizontalLine (int y, float left, float right) - { - getCanvas().callVoidMethod (Canvas.drawRect, left, (float) y, right, y + 1.0f, getCurrentPaint()); - } - - void setFont (const Font& newFont) - { - if (currentState->font != newFont) - { - currentState->font = newFont; - currentState->typefaceNeedsUpdate = true; - } - } - - const Font& getFont() - { - return currentState->font; - } - - void drawGlyph (int glyphNumber, const AffineTransform& transform) - { - if (transform.isOnlyTranslation()) - { - getCanvas().callVoidMethod (Canvas.drawText, javaStringFromChar ((juce_wchar) glyphNumber).get(), - transform.getTranslationX(), transform.getTranslationY(), - currentState->getPaintForTypeface()); - } - else - { - saveState(); - addTransform (transform); - drawGlyph (glyphNumber, AffineTransform::identity); - restoreState(); - } - } - - //============================================================================== - void saveState() - { - (void) getCanvas().callIntMethod (Canvas.save); - stateStack.add (new SavedState (*currentState)); - } - - void restoreState() - { - SavedState* const top = stateStack.getLast(); - - if (top != 0) - { - currentState->flattenImageClippingLayer (top->canvas); - - currentState = top; - stateStack.removeLast (1, false); - } - else - { - jassertfalse; // trying to pop with an empty stack! - } - - getCanvas().callVoidMethod (Canvas.restore); - } - - void beginTransparencyLayer (float opacity) - { - Rectangle clip (getClipBounds()); - - (void) getCanvas().callIntMethod (Canvas.saveLayerAlpha, - (float) clip.getX(), - (float) clip.getY(), - (float) clip.getRight(), - (float) clip.getBottom(), - jlimit (0, 255, roundToInt (opacity * 255.0f)), - 31 /*ALL_SAVE_FLAG*/); - - stateStack.add (new SavedState (*currentState)); - } - - void endTransparencyLayer() - { - restoreState(); - } - - //============================================================================== - class SavedState - { - public: - SavedState (jobject canvas_) - : canvas (canvas_), font (1.0f), quality (Graphics::highResamplingQuality), - fillNeedsUpdate (true), typefaceNeedsUpdate (true) - { - } - - SavedState (const SavedState& other) - : canvas (other.canvas), fillType (other.fillType), font (other.font), - quality (other.quality), fillNeedsUpdate (true), typefaceNeedsUpdate (true) - { - } - - void setFillType (const FillType& newType) - { - fillNeedsUpdate = true; - fillType = newType; - } - - void setAlpha (float alpha) - { - fillNeedsUpdate = true; - fillType.colour = fillType.colour.withAlpha (alpha); - } - - void setInterpolationQuality (Graphics::ResamplingQuality quality_) - { - if (quality != quality_) - { - quality = quality_; - fillNeedsUpdate = true; - paint.clear(); - } - } - - jobject getPaint() - { - if (fillNeedsUpdate) - { - JNIEnv* env = getEnv(); - - if (paint.get() == 0) - paint = GlobalRef (GraphicsHelpers::createPaint (quality)); - - if (fillType.isColour()) - { - env->DeleteLocalRef (paint.callObjectMethod (Paint.setShader, (jobject) 0)); - paint.callVoidMethod (Paint.setColor, colourToInt (fillType.colour)); - } - else if (fillType.isGradient()) - { - const ColourGradient& g = *fillType.gradient; - const Point p1 (g.point1); - const Point p2 (g.point2); - - const int numColours = g.getNumColours(); - jintArray coloursArray = env->NewIntArray (numColours); - jfloatArray positionsArray = env->NewFloatArray (numColours); - - { - HeapBlock colours (numColours); - HeapBlock positions (numColours); - - for (int i = 0; i < numColours; ++i) - { - colours[i] = colourToInt (g.getColour (i)); - positions[i] = (float) g.getColourPosition(i); - } - - env->SetIntArrayRegion (coloursArray, 0, numColours, colours.getData()); - env->SetFloatArrayRegion (positionsArray, 0, numColours, positions.getData()); - } - - jobject tileMode = env->GetStaticObjectField (ShaderTileMode, ShaderTileMode.CLAMP); - - jobject shader; - if (fillType.gradient->isRadial) - { - shader = env->NewObject (RadialGradientClass, - RadialGradientClass.constructor, - p1.getX(), p1.getY(), - p1.getDistanceFrom (p2), - coloursArray, positionsArray, - tileMode); - } - else - { - shader = env->NewObject (LinearGradientClass, - LinearGradientClass.constructor, - p1.getX(), p1.getY(), p2.getX(), p2.getY(), - coloursArray, positionsArray, - tileMode); - } - - env->DeleteLocalRef (tileMode); - env->DeleteLocalRef (coloursArray); - env->DeleteLocalRef (positionsArray); - - env->CallVoidMethod (shader, ShaderClass.setLocalMatrix, createMatrixRef (env, fillType.transform).get()); - env->DeleteLocalRef (paint.callObjectMethod (Paint.setShader, shader)); - - env->DeleteLocalRef (shader); - } - else - { - // TODO xxx - } - } - - return paint.get(); - } - - jobject getPaintForTypeface() - { - jobject p = getPaint(); - - if (typefaceNeedsUpdate) - { - typefaceNeedsUpdate = false; - const Typeface::Ptr t (font.getTypeface()); - AndroidTypeface* atf = dynamic_cast (t.getObject()); - - if (atf != 0) - { - paint.callObjectMethod (Paint.setTypeface, atf->typeface.get()); - paint.callVoidMethod (Paint.setTextSize, font.getHeight()); - - const float hScale = font.getHorizontalScale(); - - if (hScale < 0.99f || hScale > 1.01f) - paint.callVoidMethod (Paint.setTextScaleX, hScale); - } - - fillNeedsUpdate = true; - paint.callVoidMethod (Paint.setAlpha, (jint) fillType.colour.getAlpha()); - } - - return p; - } - - jobject getImagePaint() - { - jobject p = getPaint(); - paint.callVoidMethod (Paint.setAlpha, (jint) fillType.colour.getAlpha()); - fillNeedsUpdate = true; - return p; - } - - void flattenImageClippingLayer (jobject previousCanvas) - { - // XXX couldn't get image clipping to work... - - if (temporaryLayerBitmap != 0) - { - JNIEnv* env = getEnv(); - - jobject tileMode = env->GetStaticObjectField (ShaderTileMode, ShaderTileMode.CLAMP); - jobject shader = env->NewObject (BitmapShader, BitmapShader.constructor, - temporaryLayerBitmap.get(), tileMode, tileMode); - env->DeleteLocalRef (tileMode); - - jobject compositingPaint = GraphicsHelpers::createPaint (quality); - env->CallObjectMethod (compositingPaint, Paint.setShader, shader); - env->DeleteLocalRef (shader); - - LocalRef maskBitmap (createAlphaBitmap (env, maskImage)); - maskImage = Image::null; - - env->CallVoidMethod (previousCanvas, Canvas.drawBitmapAt, - maskBitmap.get(), (jfloat) maskLayerX, (jfloat) maskLayerY, compositingPaint); - - env->DeleteLocalRef (compositingPaint); - - canvas = GlobalRef (previousCanvas); - - env->CallVoidMethod (temporaryLayerBitmap.get(), BitmapClass.recycle); - env->CallVoidMethod (maskBitmap.get(), BitmapClass.recycle); - - temporaryLayerBitmap.clear(); - } - } - - void clipToImage (jobject previousCanvas, - jobject temporaryCanvas, jobject temporaryLayerBitmap_, - const Image& maskImage_, - int maskLayerX_, int maskLayerY_) - { - // XXX couldn't get image clipping to work... - flattenImageClippingLayer (previousCanvas); - - maskLayerX = maskLayerX_; - maskLayerY = maskLayerY_; - canvas = GlobalRef (temporaryCanvas); - temporaryLayerBitmap = GlobalRef (temporaryLayerBitmap_); - maskImage = maskImage_; - } - - static jobject createAlphaBitmap (JNIEnv* env, const Image& image) - { - Image::BitmapData bm (image, Image::BitmapData::readOnly); - - jobject bitmap = AndroidImage::createBitmap (bm.width, bm.height, true); - - jintArray intArray = env->NewIntArray (bm.width * bm.height); - jint* const dest = env->GetIntArrayElements (intArray, 0); - - for (int yy = 0; yy < bm.height; ++yy) - { - PixelAlpha* src = (PixelAlpha*) bm.getLinePointer (yy); - jint* destLine = dest + yy * bm.width; - - for (int xx = 0; xx < bm.width; ++xx) - { - destLine[xx] = src->getAlpha(); - src = addBytesToPointer (src, bm.pixelStride); - } - } - - env->ReleaseIntArrayElements (intArray, (jint*) dest, 0); - env->CallVoidMethod (bitmap, BitmapClass.setPixels, intArray, 0, bm.width, 0, 0, bm.width, bm.height); - env->DeleteLocalRef (intArray); - return bitmap; - } - - GlobalRef canvas, temporaryLayerBitmap; - FillType fillType; - Font font; - GlobalRef paint; - bool fillNeedsUpdate, typefaceNeedsUpdate; - Graphics::ResamplingQuality quality; - Image maskImage; - int maskLayerX, maskLayerY; - }; - -private: - //============================================================================== - GlobalRef originalCanvas; - - ScopedPointer currentState; - OwnedArray stateStack; - - GlobalRef& getCanvas() const noexcept { return currentState->canvas; } - - jobject getCurrentPaint() const { return currentState->getPaint(); } - jobject getImagePaint() const { return currentState->getImagePaint(); } - - static LocalRef createPath (JNIEnv* env, const Path& path) - { - jobject p = env->NewObject (PathClass, PathClass.constructor); - - Path::Iterator i (path); - - while (i.next()) - { - switch (i.elementType) - { - case Path::Iterator::startNewSubPath: env->CallVoidMethod (p, PathClass.moveTo, i.x1, i.y1); break; - case Path::Iterator::lineTo: env->CallVoidMethod (p, PathClass.lineTo, i.x1, i.y1); break; - case Path::Iterator::quadraticTo: env->CallVoidMethod (p, PathClass.quadTo, i.x1, i.y1, i.x2, i.y2); break; - case Path::Iterator::cubicTo: env->CallVoidMethod (p, PathClass.cubicTo, i.x1, i.y1, i.x2, i.y2, i.x3, i.y3); break; - case Path::Iterator::closePath: env->CallVoidMethod (p, PathClass.closePath); break; - default: jassertfalse; break; - } - } - - return LocalRef (p); - } - - static LocalRef createPath (JNIEnv* env, const Path& path, const AffineTransform& transform) - { - if (transform.isIdentity()) - return createPath (env, path); - - Path tempPath (path); - tempPath.applyTransform (transform); - return createPath (env, tempPath); - } - - static LocalRef createMatrixRef (JNIEnv* env, const AffineTransform& t) - { - return LocalRef (GraphicsHelpers::createMatrix (env, t)); - } - - static LocalRef createRect (JNIEnv* env, const Rectangle& r) - { - return LocalRef (env->NewObject (RectClass, RectClass.constructor, - r.getX(), r.getY(), r.getRight(), r.getBottom())); - } - - static LocalRef createRegion (JNIEnv* env, const RectangleList& list) - { - jobject region = env->NewObject (RegionClass, RegionClass.constructor); - - const int numRects = list.getNumRectangles(); - - for (int i = 0; i < numRects; ++i) - env->CallBooleanMethod (region, RegionClass.regionUnion, createRect (env, list.getRectangle(i)).get()); - - return LocalRef (region); - } - - static int colourToInt (const Colour& col) noexcept - { - return col.getARGB(); - } - - template - static void copyPixels (jint* const dest, const PixelType* src, const int width, const int pixelStride) noexcept - { - for (int x = 0; x < width; ++x) - { - dest[x] = src->getUnpremultipliedARGB(); - src = addBytesToPointer (src, pixelStride); - } - } - - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AndroidLowLevelGraphicsContext); -}; - -LowLevelGraphicsContext* AndroidImage::createLowLevelContext() -{ - jobject canvas = getEnv()->NewObject (Canvas, Canvas.constructor, bitmap.get()); - return new AndroidLowLevelGraphicsContext (canvas); -} -#endif diff --git a/modules/juce_gui_basics/commands/juce_ApplicationCommandTarget.cpp b/modules/juce_gui_basics/commands/juce_ApplicationCommandTarget.cpp index a790f3ace2..fc8e30bb61 100644 --- a/modules/juce_gui_basics/commands/juce_ApplicationCommandTarget.cpp +++ b/modules/juce_gui_basics/commands/juce_ApplicationCommandTarget.cpp @@ -23,37 +23,26 @@ ============================================================================== */ -class ApplicationCommandTarget::MessageTarget : public MessageListener +class ApplicationCommandTarget::CommandMessage : public MessageManager::MessageBase { public: - MessageTarget (ApplicationCommandTarget& owner_) - : owner (owner_) + CommandMessage (ApplicationCommandTarget* const owner_, const InvocationInfo& info_) + : owner (owner_), info (info_) { } - void handleMessage (const Message& message) + void messageCallback() { - jassert (dynamic_cast (&message) != nullptr); - - owner.tryToInvoke (dynamic_cast (message).info, false); + ApplicationCommandTarget* const target = owner; + if (target != nullptr) + target->tryToInvoke (info, false); } - struct InvokedMessage : public Message - { - InvokedMessage (const InvocationInfo& info_) - : info (info_) - {} - - const InvocationInfo info; - - private: - JUCE_DECLARE_NON_COPYABLE (InvokedMessage); - }; - private: - ApplicationCommandTarget& owner; + WeakReference owner; + const InvocationInfo info; - JUCE_DECLARE_NON_COPYABLE (MessageTarget); + JUCE_DECLARE_NON_COPYABLE (CommandMessage); }; //============================================================================== @@ -63,7 +52,7 @@ ApplicationCommandTarget::ApplicationCommandTarget() ApplicationCommandTarget::~ApplicationCommandTarget() { - messageInvoker = nullptr; + masterReference.clear(); } //============================================================================== @@ -73,10 +62,7 @@ bool ApplicationCommandTarget::tryToInvoke (const InvocationInfo& info, const bo { if (async) { - if (messageInvoker == nullptr) - messageInvoker = new MessageTarget (*this); - - messageInvoker->postMessage (new MessageTarget::InvokedMessage (info)); + (new CommandMessage (this, info))->post(); return true; } else diff --git a/modules/juce_gui_basics/commands/juce_ApplicationCommandTarget.h b/modules/juce_gui_basics/commands/juce_ApplicationCommandTarget.h index 644b635579..1833898ea8 100644 --- a/modules/juce_gui_basics/commands/juce_ApplicationCommandTarget.h +++ b/modules/juce_gui_basics/commands/juce_ApplicationCommandTarget.h @@ -234,12 +234,13 @@ public: private: //============================================================================== - class MessageTarget; - friend class MessageTarget; - friend class ScopedPointer; - ScopedPointer messageInvoker; + WeakReference::Master masterReference; + friend class WeakReference; - bool tryToInvoke (const InvocationInfo& info, bool async); + class CommandMessage; + friend class CommandMessage; + + bool tryToInvoke (const InvocationInfo&, bool async); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ApplicationCommandTarget); }; diff --git a/modules/juce_gui_basics/filebrowser/juce_FileListComponent.cpp b/modules/juce_gui_basics/filebrowser/juce_FileListComponent.cpp index e6414065d8..70caa16e04 100644 --- a/modules/juce_gui_basics/filebrowser/juce_FileListComponent.cpp +++ b/modules/juce_gui_basics/filebrowser/juce_FileListComponent.cpp @@ -228,13 +228,12 @@ void FileListComponent::paintListBoxItem (int, Graphics&, int, int, bool) Component* FileListComponent::refreshComponentForRow (int row, bool isSelected, Component* existingComponentToUpdate) { - FileListItemComponent* comp = dynamic_cast (existingComponentToUpdate); + jassert (existingComponentToUpdate == nullptr || dynamic_cast (existingComponentToUpdate) != nullptr); + + FileListItemComponent* comp = static_cast (existingComponentToUpdate); if (comp == nullptr) - { - delete existingComponentToUpdate; comp = new FileListItemComponent (*this, fileList.getTimeSliceThread()); - } DirectoryContentsList::FileInfo fileInfo; comp->update (fileList.getDirectory(), diff --git a/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp b/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp index 87110e17b0..1c84037ccc 100644 --- a/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp +++ b/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp @@ -100,7 +100,8 @@ public: { const bool wasVisible = isVisible(); setVisible (false); - finalTarget = findTarget (e.getScreenPosition(), details.localPosition); + Component* unused; + finalTarget = findTarget (e.getScreenPosition(), details.localPosition, unused); if (wasVisible) // fade the component and remove it - it'll be deleted later by the timer callback dismissWithAnimation (finalTarget == nullptr); @@ -131,8 +132,8 @@ public: setNewScreenPos (screenPos); - DragAndDropTarget* const newTarget = findTarget (screenPos, details.localPosition); - Component* newTargetComp = dynamic_cast (newTarget); + Component* newTargetComp; + DragAndDropTarget* const newTarget = findTarget (screenPos, details.localPosition, newTargetComp); setVisible (newTarget == nullptr || newTarget->shouldDrawDragImageWhenOver()); @@ -185,7 +186,8 @@ private: return dynamic_cast (currentlyOverComp.get()); } - DragAndDropTarget* findTarget (const Point& screenPos, Point& relativePos) const + DragAndDropTarget* findTarget (const Point& screenPos, Point& relativePos, + Component*& resultComponent) const { Component* hit = getParentComponent(); @@ -205,12 +207,14 @@ private: if (ddt != nullptr && ddt->isInterestedInDragSource (details)) { relativePos = hit->getLocalPoint (nullptr, screenPos); + resultComponent = hit; return ddt; } hit = hit->getParentComponent(); } + resultComponent = nullptr; return nullptr; } @@ -304,14 +308,6 @@ void DragAndDropContainer::startDragging (const var& sourceDescription, if (dragImageComponent == nullptr) { - Component* const thisComp = dynamic_cast (this); - - if (thisComp == nullptr) - { - jassertfalse; // Your DragAndDropContainer needs to be a Component! - return; - } - MouseInputSource* draggingSource = Desktop::getInstance().getDraggingMouseSource (0); if (draggingSource == nullptr || ! draggingSource->isDragging()) @@ -382,7 +378,17 @@ void DragAndDropContainer::startDragging (const var& sourceDescription, | ComponentPeer::windowIgnoresKeyPresses); } else + { + Component* const thisComp = dynamic_cast (this); + + if (thisComp == nullptr) + { + jassertfalse; // Your DragAndDropContainer needs to be a Component! + return; + } + thisComp->addChildComponent (dragImageComponent); + } static_cast (dragImageComponent.get())->updateLocation (false, lastMouseDown); dragImageComponent->setVisible (true); diff --git a/modules/juce_gui_basics/native/juce_android_Windowing.cpp b/modules/juce_gui_basics/native/juce_android_Windowing.cpp index 36e257870a..24fabdfc85 100644 --- a/modules/juce_gui_basics/native/juce_android_Windowing.cpp +++ b/modules/juce_gui_basics/native/juce_android_Windowing.cpp @@ -375,53 +375,43 @@ public: //============================================================================== void handlePaintCallback (JNIEnv* env, jobject canvas) { - #if USE_ANDROID_CANVAS - if (usingAndroidGraphics) + jobject rect = env->CallObjectMethod (canvas, CanvasMinimal.getClipBounds); + const int left = env->GetIntField (rect, RectClass.left); + const int top = env->GetIntField (rect, RectClass.top); + const int right = env->GetIntField (rect, RectClass.right); + const int bottom = env->GetIntField (rect, RectClass.bottom); + env->DeleteLocalRef (rect); + + const Rectangle clip (left, top, right - left, bottom - top); + + const int sizeNeeded = clip.getWidth() * clip.getHeight(); + if (sizeAllocated < sizeNeeded) { - AndroidLowLevelGraphicsContext g (canvas); - handlePaint (g); + buffer.clear(); + sizeAllocated = sizeNeeded; + buffer = GlobalRef (env->NewIntArray (sizeNeeded)); } - else - #endif + + jint* dest = env->GetIntArrayElements ((jintArray) buffer.get(), 0); + + if (dest != 0) { - jobject rect = env->CallObjectMethod (canvas, CanvasMinimal.getClipBounds); - const int left = env->GetIntField (rect, RectClass.left); - const int top = env->GetIntField (rect, RectClass.top); - const int right = env->GetIntField (rect, RectClass.right); - const int bottom = env->GetIntField (rect, RectClass.bottom); - env->DeleteLocalRef (rect); - - const Rectangle clip (left, top, right - left, bottom - top); - - const int sizeNeeded = clip.getWidth() * clip.getHeight(); - if (sizeAllocated < sizeNeeded) { - buffer.clear(); - sizeAllocated = sizeNeeded; - buffer = GlobalRef (env->NewIntArray (sizeNeeded)); - } + Image temp (new PreallocatedImage (clip.getWidth(), clip.getHeight(), + dest, ! component->isOpaque())); - jint* dest = env->GetIntArrayElements ((jintArray) buffer.get(), 0); - - if (dest != 0) - { { - Image temp (new PreallocatedImage (clip.getWidth(), clip.getHeight(), - dest, ! component->isOpaque())); - - { - LowLevelGraphicsSoftwareRenderer g (temp); - g.setOrigin (-clip.getX(), -clip.getY()); - handlePaint (g); - } + LowLevelGraphicsSoftwareRenderer g (temp); + g.setOrigin (-clip.getX(), -clip.getY()); + handlePaint (g); } - - env->ReleaseIntArrayElements ((jintArray) buffer.get(), dest, 0); - - env->CallVoidMethod (canvas, CanvasMinimal.drawBitmap, (jintArray) buffer.get(), 0, clip.getWidth(), - (jfloat) clip.getX(), (jfloat) clip.getY(), - clip.getWidth(), clip.getHeight(), true, (jobject) 0); } + + env->ReleaseIntArrayElements ((jintArray) buffer.get(), dest, 0); + + env->CallVoidMethod (canvas, CanvasMinimal.drawBitmap, (jintArray) buffer.get(), 0, clip.getWidth(), + (jfloat) clip.getX(), (jfloat) clip.getY(), + clip.getWidth(), clip.getHeight(), true, (jobject) 0); } } diff --git a/modules/juce_gui_basics/widgets/juce_ToolbarItemComponent.cpp b/modules/juce_gui_basics/widgets/juce_ToolbarItemComponent.cpp index 4d69a761dc..e1ebd2f965 100644 --- a/modules/juce_gui_basics/widgets/juce_ToolbarItemComponent.cpp +++ b/modules/juce_gui_basics/widgets/juce_ToolbarItemComponent.cpp @@ -45,7 +45,7 @@ public: void paint (Graphics& g) { - ToolbarItemComponent* const tc = dynamic_cast (getParentComponent()); + ToolbarItemComponent* const tc = getToolbarItemComponent(); if (isMouseOverOrDragging() && tc != nullptr @@ -60,7 +60,7 @@ public: void mouseDown (const MouseEvent& e) { isDragging = false; - ToolbarItemComponent* const tc = dynamic_cast (getParentComponent()); + ToolbarItemComponent* const tc = getToolbarItemComponent(); if (tc != nullptr) { @@ -80,7 +80,7 @@ public: { dnd->startDragging (Toolbar::toolbarDragDescriptor, getParentComponent(), Image::null, true); - ToolbarItemComponent* const tc = dynamic_cast (getParentComponent()); + ToolbarItemComponent* const tc = getToolbarItemComponent(); if (tc != nullptr) { @@ -96,7 +96,7 @@ public: void mouseUp (const MouseEvent&) { isDragging = false; - ToolbarItemComponent* const tc = dynamic_cast (getParentComponent()); + ToolbarItemComponent* const tc = getToolbarItemComponent(); if (tc != nullptr) { @@ -120,6 +120,11 @@ private: //============================================================================== bool isDragging; + ToolbarItemComponent* getToolbarItemComponent() const noexcept + { + return dynamic_cast (getParentComponent()); + } + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ItemDragAndDropOverlayComponent); }; diff --git a/modules/juce_gui_basics/widgets/juce_TreeView.cpp b/modules/juce_gui_basics/widgets/juce_TreeView.cpp index a228d52662..d788d7c379 100644 --- a/modules/juce_gui_basics/widgets/juce_TreeView.cpp +++ b/modules/juce_gui_basics/widgets/juce_TreeView.cpp @@ -441,7 +441,7 @@ public: bool keyPressed (const KeyPress& key) { - TreeView* const tree = dynamic_cast (getParentComponent()); + Component* const tree = getParentComponent(); return (tree != nullptr && tree->keyPressed (key)) || Viewport::keyPressed (key); diff --git a/modules/juce_gui_basics/windows/juce_ComponentPeer.cpp b/modules/juce_gui_basics/windows/juce_ComponentPeer.cpp index cdbb483041..b7aec19973 100644 --- a/modules/juce_gui_basics/windows/juce_ComponentPeer.cpp +++ b/modules/juce_gui_basics/windows/juce_ComponentPeer.cpp @@ -434,7 +434,7 @@ bool ComponentPeer::handleFileDragMove (const StringArray& files, const Point (static_cast (dragAndDropTargetComponent)); + = dynamic_cast (dragAndDropTargetComponent.get()); FileDragAndDropTarget* newTarget = nullptr; @@ -468,8 +468,7 @@ bool ComponentPeer::handleFileDragMove (const StringArray& files, const Point (newTarget); - const Point pos (targetComp->getLocalPoint (component, position)); + const Point pos (dragAndDropTargetComponent->getLocalPoint (component, position)); newTarget->fileDragMove (files, pos.getX(), pos.getY()); return true; } @@ -515,16 +514,14 @@ bool ComponentPeer::handleFileDragDrop (const StringArray& files, const Point (static_cast (dragAndDropTargetComponent)); + Component* const targetComp = dragAndDropTargetComponent; + FileDragAndDropTarget* const target = dynamic_cast (targetComp); dragAndDropTargetComponent = nullptr; lastDragAndDropCompUnderMouse = nullptr; if (target != nullptr) { - Component* const targetComp = dynamic_cast (target); - if (targetComp->isCurrentlyBlockedByAnotherModalComponent()) { targetComp->internalModalInputAttempt();