From 413e00631b765f898d99e730e3e56b072ea59475 Mon Sep 17 00:00:00 2001 From: Julian Storer Date: Tue, 1 Feb 2011 14:58:40 +0000 Subject: [PATCH] TextEditor and Colour fixes. --- juce_amalgamated.cpp | 405 +++++++++++++----- juce_amalgamated.h | 31 +- src/audio/devices/juce_AudioDeviceManager.cpp | 25 +- src/audio/dsp/juce_AudioSampleBuffer.cpp | 20 +- src/audio/dsp/juce_AudioSampleBuffer.h | 23 +- src/core/juce_StandardHeader.h | 2 +- src/core/juce_TargetPlatform.h | 6 +- .../components/controls/juce_TextEditor.cpp | 2 +- src/gui/graphics/colour/juce_Colour.cpp | 33 +- .../android/juce_android_GraphicsContext.cpp | 16 +- src/native/android/juce_android_Misc.cpp | 36 ++ .../android/juce_android_NativeCode.cpp | 206 ++++++++- .../android/juce_android_SystemStats.cpp | 74 ---- src/native/android/juce_android_Windowing.cpp | 53 ++- 14 files changed, 683 insertions(+), 249 deletions(-) diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 174e1cb736..dcbc262c37 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -58,6 +58,9 @@ #if (defined (_WIN32) || defined (_WIN64)) #define JUCE_WIN32 1 #define JUCE_WINDOWS 1 +#elif defined (JUCE_ANDROID) + #undef JUCE_ANDROID + #define JUCE_ANDROID 1 #elif defined (LINUX) || defined (__linux__) #define JUCE_LINUX 1 #elif defined (__APPLE_CPP__) || defined(__APPLE_CC__) @@ -69,9 +72,6 @@ #else #define JUCE_MAC 1 #endif -#elif defined (JUCE_ANDROID) - #undef JUCE_ANDROID - #define JUCE_ANDROID 1 #else #error "Unknown platform!" #endif @@ -25746,34 +25746,21 @@ void AudioDeviceManager::addMidiInputCallback (const String& name, { removeMidiInputCallback (name, callbackToAdd); - if (name.isEmpty()) + if (name.isEmpty() || isMidiInputEnabled (name)) { + const ScopedLock sl (midiCallbackLock); midiCallbacks.add (callbackToAdd); - midiCallbackDevices.add (String::empty); - } - else - { - for (int i = enabledMidiInputs.size(); --i >= 0;) - { - if (enabledMidiInputs[i]->getName() == name) - { - const ScopedLock sl (midiCallbackLock); - midiCallbacks.add (callbackToAdd); - midiCallbackDevices.add (enabledMidiInputs[i]->getName()); - break; - } - } + midiCallbackDevices.add (name); } } -void AudioDeviceManager::removeMidiInputCallback (const String& name, MidiInputCallback* /*callback*/) +void AudioDeviceManager::removeMidiInputCallback (const String& name, MidiInputCallback* callback) { - const ScopedLock sl (midiCallbackLock); - for (int i = midiCallbacks.size(); --i >= 0;) { - if (midiCallbackDevices[i] == name) + if (midiCallbackDevices[i] == name && midiCallbacks.getUnchecked(i) == callback) { + const ScopedLock sl (midiCallbackLock); midiCallbacks.remove (i); midiCallbackDevices.remove (i); } @@ -26782,7 +26769,19 @@ AudioSampleBuffer::AudioSampleBuffer (float** dataToReferTo, allocatedBytes (0) { jassert (numChannels_ > 0); - allocateChannels (dataToReferTo); + allocateChannels (dataToReferTo, 0); +} + +AudioSampleBuffer::AudioSampleBuffer (float** dataToReferTo, + const int numChannels_, + const int startSample, + const int numSamples) throw() + : numChannels (numChannels_), + size (numSamples), + allocatedBytes (0) +{ + jassert (numChannels_ > 0); + allocateChannels (dataToReferTo, startSample); } void AudioSampleBuffer::setDataToReferTo (float** dataToReferTo, @@ -26797,10 +26796,10 @@ void AudioSampleBuffer::setDataToReferTo (float** dataToReferTo, numChannels = newNumChannels; size = newNumSamples; - allocateChannels (dataToReferTo); + allocateChannels (dataToReferTo, 0); } -void AudioSampleBuffer::allocateChannels (float** const dataToReferTo) +void AudioSampleBuffer::allocateChannels (float** const dataToReferTo, int offset) { // (try to avoid doing a malloc here, as that'll blow up things like Pro-Tools) if (numChannels < numElementsInArray (preallocatedChannelSpace)) @@ -26818,7 +26817,7 @@ void AudioSampleBuffer::allocateChannels (float** const dataToReferTo) // you have to pass in the same number of valid pointers as numChannels jassert (dataToReferTo[i] != 0); - channels[i] = dataToReferTo[i]; + channels[i] = dataToReferTo[i] + offset; } channels [numChannels] = 0; @@ -52200,7 +52199,7 @@ private: } else { - while (! text.isEmpty() || text.isWhitespace()) + while (! (text.isEmpty() || text.isWhitespace())) { ++text; ++numChars; @@ -80262,23 +80261,19 @@ namespace ColourHelpers else { s = jmin (1.0f, s); - h = jlimit (0.0f, 1.0f, h); h = (h - std::floor (h)) * 6.0f + 0.00001f; // need a small adjustment to compensate for rounding errors const float f = h - std::floor (h); - const uint8 x = (uint8) roundToInt (v * (1.0f - s)); - const float y = v * (1.0f - s * f); - const float z = v * (1.0f - (s * (1.0f - f))); if (h < 1.0f) { r = intV; - g = (uint8) roundToInt (z); + g = (uint8) roundToInt (v * (1.0f - (s * (1.0f - f)))); b = x; } else if (h < 2.0f) { - r = (uint8) roundToInt (y); + r = (uint8) roundToInt (v * (1.0f - s * f)); g = intV; b = x; } @@ -80286,31 +80281,25 @@ namespace ColourHelpers { r = x; g = intV; - b = (uint8) roundToInt (z); + b = (uint8) roundToInt (v * (1.0f - (s * (1.0f - f)))); } else if (h < 4.0f) { r = x; - g = (uint8) roundToInt (y); + g = (uint8) roundToInt (v * (1.0f - s * f)); b = intV; } else if (h < 5.0f) { - r = (uint8) roundToInt (z); + r = (uint8) roundToInt (v * (1.0f - (s * (1.0f - f)))); g = x; b = intV; } - else if (h < 6.0f) + else { r = intV; g = x; - b = (uint8) roundToInt (y); - } - else - { - r = 0; - g = 0; - b = 0; + b = (uint8) roundToInt (v * (1.0f - s * f)); } } } @@ -80398,7 +80387,7 @@ Colour::Colour (const float hue, const float brightness, const float alpha) throw() { - uint8 r = getRed(), g = getGreen(), b = getBlue(); + uint8 r, g, b; ColourHelpers::convertHSBtoRGB (hue, saturation, brightness, r, g, b); argb.setARGB (ColourHelpers::floatAlphaToInt (alpha), r, g, b); @@ -80417,7 +80406,7 @@ Colour::Colour (const float hue, const float brightness, const uint8 alpha) throw() { - uint8 r = getRed(), g = getGreen(), b = getBlue(); + uint8 r, g, b; ColourHelpers::convertHSBtoRGB (hue, saturation, brightness, r, g, b); argb.setARGB (alpha, r, g, b); @@ -80604,10 +80593,7 @@ const Colour Colour::withRotatedHue (const float amountToRotate) const throw() float h, s, b; getHSB (h, s, b); - h += amountToRotate; - h -= std::floor (h); - - return Colour (h, s, b, getAlpha()); + return Colour (h + amountToRotate, s, b, getAlpha()); } float Colour::getSaturation() const throw() @@ -278509,18 +278495,126 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE -#define JUCE_INCLUDED_FILE 1 +#define JUCE_JNI_CALLBACK(className, methodName, returnType, params) \ + extern "C" __attribute__ ((visibility("default"))) returnType Java_com_juce_ ## className ## _ ## methodName params -// Now include the actual code files.. +#define JUCE_JNI_CLASSES(JAVACLASS) \ + JAVACLASS (activityClass, "com/juce/JuceAppActivity") \ + JAVACLASS (componentPeerViewClass, "com/juce/ComponentPeerView") \ + JAVACLASS (fileClass, "java/io/File") \ + JAVACLASS (contextClass, "android/content/Context") \ + JAVACLASS (canvasClass, "android/graphics/Canvas") \ + JAVACLASS (paintClass, "android/graphics/Paint") \ -/*** Start of inlined file: juce_android_SystemStats.cpp ***/ -// (This file gets included by juce_android_NativeCode.cpp, rather than being -// compiled on its own). -#if JUCE_INCLUDED_FILE +#define JUCE_JNI_METHODS(METHOD, STATICMETHOD) \ +\ + STATICMETHOD (activityClass, printToConsole, "printToConsole", "(Ljava/lang/String;)V") \ + METHOD (activityClass, createNewView, "createNewView", "()Lcom/juce/ComponentPeerView;") \ + METHOD (activityClass, deleteView, "deleteView", "(Lcom/juce/ComponentPeerView;)V") \ +\ + METHOD (fileClass, fileExists, "exists", "()Z") \ +\ + METHOD (componentPeerViewClass, layout, "layout", "(IIII)V") \ +\ + METHOD (canvasClass, drawRect, "drawRect", "(FFFFLandroid/graphics/Paint;)V") \ +\ + METHOD (paintClass, paintClassConstructor, "", "()V") \ + METHOD (paintClass, setColor, "setColor", "(I)V") \ -END_JUCE_NAMESPACE -extern JUCE_NAMESPACE::JUCEApplication* juce_CreateApplication(); // (from START_JUCE_APPLICATION) -BEGIN_JUCE_NAMESPACE +class GlobalRef +{ +public: + GlobalRef() + : env (0), obj (0) + { + } + + GlobalRef (JNIEnv* const env_, jobject obj_) + : env (env_), + obj (retain (env_, obj_)) + { + } + + GlobalRef (const GlobalRef& other) + : env (other.env), + obj (retain (other.env, other.obj)) + { + } + + ~GlobalRef() + { + release(); + } + + GlobalRef& operator= (const GlobalRef& other) + { + release(); + env = other.env; + obj = retain (env, other.obj); + return *this; + } + + GlobalRef& operator= (jobject newObj) + { + jassert (env != 0 || newObj == 0); + + if (newObj != obj && env != 0) + { + release(); + obj = retain (env, newObj); + } + } + + inline operator jobject() const throw() { return obj; } + inline jobject get() const throw() { return obj; } + + inline JNIEnv* getEnv() const throw() { return env; } + + #define DECLARE_CALL_TYPE_METHOD(returnType, typeName) \ + returnType call##typeName##Method (jmethodID methodID, ... ) \ + { \ + returnType result; \ + va_list args; \ + va_start (args, methodID); \ + result = env->Call##typeName##MethodV (obj, methodID, args); \ + va_end (args); \ + return result; \ + } + + DECLARE_CALL_TYPE_METHOD (jobject, Object) + DECLARE_CALL_TYPE_METHOD (jboolean, Boolean) + DECLARE_CALL_TYPE_METHOD (jbyte, Byte) + DECLARE_CALL_TYPE_METHOD (jchar, Char) + DECLARE_CALL_TYPE_METHOD (jshort, Short) + DECLARE_CALL_TYPE_METHOD (jint, Int) + DECLARE_CALL_TYPE_METHOD (jlong, Long) + DECLARE_CALL_TYPE_METHOD (jfloat, Float) + DECLARE_CALL_TYPE_METHOD (jdouble, Double) + #undef DECLARE_CALL_TYPE_METHOD + + void callVoidMethod (jmethodID methodID, ... ) + { + va_list args; + va_start (args, methodID); + env->CallVoidMethodV (obj, methodID, args); + va_end (args); + } + +private: + JNIEnv* env; + jobject obj; + + void release() + { + if (env != 0) + env->DeleteGlobalRef (obj); + } + + static jobject retain (JNIEnv* const env, jobject obj_) + { + return env == 0 ? 0 : env->NewGlobalRef (obj_); + } +}; class AndroidJavaCallbacks { @@ -278529,37 +278623,85 @@ public: { } - void initialise (JNIEnv* env_, jobject activity) + void initialise (JNIEnv* env_, jobject activity_) { env = env_; - activityClass = (jclass) env->NewGlobalRef (env->GetObjectClass (activity)); + activity = GlobalRef (env, activity_); - printToConsole = env->GetStaticMethodID (activityClass, "printToConsole", "(Ljava/lang/String;)V"); - jassert (printToConsole != 0); + #define CREATE_JNI_CLASS(className, path) \ + className = (jclass) env->NewGlobalRef (env->FindClass (path)); \ + jassert (className != 0); + JUCE_JNI_CLASSES (CREATE_JNI_CLASS); + #undef CREATE_JNI_CLASS + + #define CREATE_JNI_METHOD(ownerClass, methodID, stringName, params) \ + methodID = env->GetMethodID (ownerClass, stringName, params); \ + jassert (methodID != 0); + #define CREATE_JNI_STATICMETHOD(ownerClass, methodID, stringName, params) \ + methodID = env->GetStaticMethodID (ownerClass, stringName, params); \ + jassert (methodID != 0); + JUCE_JNI_METHODS (CREATE_JNI_METHOD, CREATE_JNI_STATICMETHOD); + #undef CREATE_JNI_METHOD } void shutdown() { if (env != 0) { - env->DeleteGlobalRef (activityClass); + #define RELEASE_JNI_CLASS(className, path) env->DeleteGlobalRef (className); + JUCE_JNI_CLASSES (RELEASE_JNI_CLASS); + #undef RELEASE_JNI_CLASS + + activity = 0; + env = 0; } } - JNIEnv* env; + const String juceString (jstring s) const + { + jboolean isCopy; + const char* const utf8 = env->GetStringUTFChars (s, &isCopy); + CharPointer_UTF8 utf8CP (utf8); + const String result (utf8CP); + env->ReleaseStringUTFChars (s, utf8); + return result; + } - jclass activityClass; - jmethodID printToConsole; + jstring javaString (const String& s) const + { + return env->NewStringUTF (s.toUTF8()); + } + + JNIEnv* env; + GlobalRef activity; + + #define DECLARE_JNI_CLASS(className, path) jclass className; + JUCE_JNI_CLASSES (DECLARE_JNI_CLASS); + #undef DECLARE_JNI_CLASS + + #define DECLARE_JNI_METHOD(ownerClass, methodID, stringName, params) jmethodID methodID; + JUCE_JNI_METHODS (DECLARE_JNI_METHOD, DECLARE_JNI_METHOD); + #undef DECLARE_JNI_METHOD }; -static AndroidJavaCallbacks androidEnv; +static AndroidJavaCallbacks android; -#define JUCE_JNI_CALLBACK(className, methodName, returnType, params) \ - extern "C" __attribute__ ((visibility("default"))) returnType Java_com_juce_launch_ ## className ## _ ## methodName params +#define JUCE_INCLUDED_FILE 1 + +// Now include the actual code files.. + +/*** Start of inlined file: juce_android_Misc.cpp ***/ +// (This file gets included by juce_android_NativeCode.cpp, rather than being +// compiled on its own). +#if JUCE_INCLUDED_FILE + +END_JUCE_NAMESPACE +extern JUCE_NAMESPACE::JUCEApplication* juce_CreateApplication(); // (from START_JUCE_APPLICATION) +BEGIN_JUCE_NAMESPACE JUCE_JNI_CALLBACK (JuceAppActivity, launchApp, void, (JNIEnv* env, jobject activity)) { - androidEnv.initialise (env, activity); + android.initialise (env, activity); JUCEApplication::createInstance = &juce_CreateApplication; @@ -278573,7 +278715,7 @@ JUCE_JNI_CALLBACK (JuceAppActivity, quitApp, void, (JNIEnv* env, jobject activit { JUCEApplication::appWillTerminateByForce(); - androidEnv.shutdown(); + android.shutdown(); } void PlatformUtilities::beep() @@ -278583,10 +278725,34 @@ void PlatformUtilities::beep() void Logger::outputDebugString (const String& text) { - androidEnv.env->CallStaticVoidMethod (androidEnv.activityClass, androidEnv.printToConsole, - androidEnv.env->NewStringUTF (text.toUTF8())); + android.env->CallStaticVoidMethod (android.activityClass, android.printToConsole, + android.javaString (text)); } +void SystemClipboard::copyTextToClipboard (const String& text) +{ + // TODO +} + +const String SystemClipboard::getTextFromClipboard() +{ + String result; + + // TODO + + return result; +} + +#endif +/*** End of inlined file: juce_android_Misc.cpp ***/ + + + +/*** Start of inlined file: juce_android_SystemStats.cpp ***/ +// (This file gets included by juce_android_NativeCode.cpp, rather than being +// compiled on its own). +#if JUCE_INCLUDED_FILE + SystemStats::OperatingSystemType SystemStats::getOperatingSystemType() { return Android; @@ -278726,7 +278892,6 @@ bool Time::setSystemTimeToThisTime() const #endif /*** End of inlined file: juce_android_SystemStats.cpp ***/ - // (must be first) /*** Start of inlined file: juce_posix_SharedCode.h ***/ /* @@ -279504,7 +279669,6 @@ void Thread::setCurrentThreadAffinityMask (const uint32 affinityMask) /*** End of inlined file: juce_posix_SharedCode.h ***/ - /*** Start of inlined file: juce_android_Files.cpp ***/ // (This file gets included by juce_android_NativeCode.cpp, rather than being // compiled on its own). @@ -280263,7 +280427,8 @@ const Typeface::Ptr Typeface::createSystemTypefaceFor (const Font& font) class AndroidLowLevelGraphicsContext : public LowLevelGraphicsContext { public: - AndroidLowLevelGraphicsContext() + AndroidLowLevelGraphicsContext (const GlobalRef& canvas_) + : canvas (canvas_) { } @@ -280288,12 +280453,12 @@ public: bool clipToRectangle (const Rectangle& r) { - return false; + return true; } bool clipToRectangleList (const RectangleList& clipRegion) { - return false; + return true; } void excludeClipRectangle (const Rectangle& r) @@ -280315,7 +280480,7 @@ public: const Rectangle getClipBounds() const { - return Rectangle(); + return Rectangle (0, 0, 1000, 1000); } bool isClipEmpty() const @@ -280341,6 +280506,8 @@ public: void setFill (const FillType& fillType) { + currentPaint = android.env->NewObject (android.paintClass, android.paintClassConstructor); + currentPaint.callVoidMethod (android.setColor, fillType.colour.getARGB()); } void setOpacity (float newOpacity) @@ -280353,6 +280520,9 @@ public: void fillRect (const Rectangle& r, bool replaceExistingContents) { + canvas.callVoidMethod (android.drawRect, + (float) r.getX(), (float) r.getY(), (float) r.getRight(), (float) r.getBottom(), + currentPaint.get()); } void fillPath (const Path& path, const AffineTransform& transform) @@ -280389,6 +280559,8 @@ public: } private: + GlobalRef canvas, currentPaint; + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AndroidLowLevelGraphicsContext); }; @@ -280408,11 +280580,13 @@ public: AndroidComponentPeer (Component* const component, const int windowStyleFlags) : ComponentPeer (component, windowStyleFlags) { - // TODO + view = GlobalRef (android.env, android.activity.callObjectMethod (android.createNewView)); } ~AndroidComponentPeer() { + android.activity.callVoidMethod (android.deleteView, view.get()); + view = 0; } void* getNativeHandle() const @@ -280439,7 +280613,8 @@ public: void setBounds (int x, int y, int w, int h, bool isNowFullScreen) { - // TODO + DBG ("Window size: " << x << " " << y << " " << w << " " << h); + view.callVoidMethod (android.layout, x, y, x + w, y + h); } const Rectangle getBounds() const @@ -280537,6 +280712,12 @@ public: // TODO } + void handlePaintCallback (JNIEnv* env, jobject canvas) + { + AndroidLowLevelGraphicsContext g (GlobalRef (env, canvas)); + handlePaint (g); + } + void repaint (const Rectangle& area) { // TODO @@ -280552,11 +280733,38 @@ public: // TODO } + static AndroidComponentPeer* findPeerForJavaView (jobject viewToFind) + { + for (int i = getNumPeers(); --i >= 0;) + { + AndroidComponentPeer* const ap = static_cast (getPeer(i)); + jassert (dynamic_cast (getPeer(i)) != 0); + + if (ap->view == viewToFind) + return ap; + } + + return 0; + } + private: + GlobalRef view; + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AndroidComponentPeer); }; +#define JUCE_VIEW_CALLBACK(returnType, javaMethodName, params, juceMethodInvocation) \ + JUCE_JNI_CALLBACK (ComponentPeerView, javaMethodName, returnType, params) \ + { \ + AndroidComponentPeer* const peer = AndroidComponentPeer::findPeerForJavaView (view); \ + if (peer != 0) \ + peer->juceMethodInvocation; \ + } + +JUCE_VIEW_CALLBACK (void, handlePaint, (JNIEnv* env, jobject view, jobject canvas), + handlePaintCallback (env, canvas)) + ComponentPeer* Component::createNewPeer (int styleFlags, void*) { return new AndroidComponentPeer (this, styleFlags); @@ -280641,11 +280849,17 @@ void juce_setKioskComponent (Component* kioskModeComponent, bool enableOrDisable { } +static int screenWidth = 0, screenHeight = 0; + void juce_updateMultiMonitorInfo (Array >& monitorCoords, const bool clipToWorkArea) { - // TODO + monitorCoords.add (Rectangle (0, 0, screenWidth, screenHeight)); +} - monitorCoords.add (Rectangle (0, 0, 640, 480)); +JUCE_JNI_CALLBACK (JuceAppActivity, setScreenSize, void, (JNIEnv* env, jobject activity, int w, int h)) +{ + screenWidth = w; + screenHeight = h; } const Image juce_createIconForFile (const File& file) @@ -280768,29 +280982,6 @@ void FileChooser::showPlatformDialog (Array& results, /*** End of inlined file: juce_android_FileChooser.cpp ***/ -/*** Start of inlined file: juce_android_Misc.cpp ***/ -// (This file gets included by juce_android_NativeCode.cpp, rather than being -// compiled on its own). -#if JUCE_INCLUDED_FILE - -void SystemClipboard::copyTextToClipboard (const String& text) -{ - // TODO -} - -const String SystemClipboard::getTextFromClipboard() -{ - String result; - - // TODO - - return result; -} - -#endif -/*** End of inlined file: juce_android_Misc.cpp ***/ - - /*** Start of inlined file: juce_android_WebBrowserComponent.cpp ***/ // (This file gets included by juce_android_NativeCode.cpp, rather than being // compiled on its own). diff --git a/juce_amalgamated.h b/juce_amalgamated.h index b00ec5fa02..131e5a5bd4 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -73,7 +73,7 @@ namespace JuceDummyNamespace {} */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 53 -#define JUCE_BUILDNUMBER 24 +#define JUCE_BUILDNUMBER 25 /** Current Juce version number. @@ -105,6 +105,9 @@ namespace JuceDummyNamespace {} #if (defined (_WIN32) || defined (_WIN64)) #define JUCE_WIN32 1 #define JUCE_WINDOWS 1 +#elif defined (JUCE_ANDROID) + #undef JUCE_ANDROID + #define JUCE_ANDROID 1 #elif defined (LINUX) || defined (__linux__) #define JUCE_LINUX 1 #elif defined (__APPLE_CPP__) || defined(__APPLE_CC__) @@ -116,9 +119,6 @@ namespace JuceDummyNamespace {} #else #define JUCE_MAC 1 #endif -#elif defined (JUCE_ANDROID) - #undef JUCE_ANDROID - #define JUCE_ANDROID 1 #else #error "Unknown platform!" #endif @@ -34408,6 +34408,27 @@ public: int numChannels, int numSamples) throw(); + /** Creates a buffer using a pre-allocated block of memory. + + Note that if the buffer is resized or its number of channels is changed, it + will re-allocate memory internally and copy the existing data to this new area, + so it will then stop directly addressing this memory. + + @param dataToReferTo a pre-allocated array containing pointers to the data + for each channel that should be used by this buffer. The + buffer will only refer to this memory, it won't try to delete + it when the buffer is deleted or resized. + @param numChannels the number of channels to use - this must correspond to the + number of elements in the array passed in + @param startSample the offset within the arrays at which the data begins + @param numSamples the number of samples to use - this must correspond to the + size of the arrays passed in + */ + AudioSampleBuffer (float** dataToReferTo, + int numChannels, + int startSample, + int numSamples) throw(); + /** Copies another buffer. This buffer will make its own copy of the other's data, unless the buffer was created @@ -34761,7 +34782,7 @@ private: float* preallocatedChannelSpace [32]; void allocateData(); - void allocateChannels (float** dataToReferTo); + void allocateChannels (float** dataToReferTo, int offset); JUCE_LEAK_DETECTOR (AudioSampleBuffer); }; diff --git a/src/audio/devices/juce_AudioDeviceManager.cpp b/src/audio/devices/juce_AudioDeviceManager.cpp index 4e48dbc887..99523b5f01 100644 --- a/src/audio/devices/juce_AudioDeviceManager.cpp +++ b/src/audio/devices/juce_AudioDeviceManager.cpp @@ -795,34 +795,21 @@ void AudioDeviceManager::addMidiInputCallback (const String& name, { removeMidiInputCallback (name, callbackToAdd); - if (name.isEmpty()) + if (name.isEmpty() || isMidiInputEnabled (name)) { + const ScopedLock sl (midiCallbackLock); midiCallbacks.add (callbackToAdd); - midiCallbackDevices.add (String::empty); - } - else - { - for (int i = enabledMidiInputs.size(); --i >= 0;) - { - if (enabledMidiInputs[i]->getName() == name) - { - const ScopedLock sl (midiCallbackLock); - midiCallbacks.add (callbackToAdd); - midiCallbackDevices.add (enabledMidiInputs[i]->getName()); - break; - } - } + midiCallbackDevices.add (name); } } -void AudioDeviceManager::removeMidiInputCallback (const String& name, MidiInputCallback* /*callback*/) +void AudioDeviceManager::removeMidiInputCallback (const String& name, MidiInputCallback* callback) { - const ScopedLock sl (midiCallbackLock); - for (int i = midiCallbacks.size(); --i >= 0;) { - if (midiCallbackDevices[i] == name) + if (midiCallbackDevices[i] == name && midiCallbacks.getUnchecked(i) == callback) { + const ScopedLock sl (midiCallbackLock); midiCallbacks.remove (i); midiCallbackDevices.remove (i); } diff --git a/src/audio/dsp/juce_AudioSampleBuffer.cpp b/src/audio/dsp/juce_AudioSampleBuffer.cpp index 93c34011ab..b902c82c46 100644 --- a/src/audio/dsp/juce_AudioSampleBuffer.cpp +++ b/src/audio/dsp/juce_AudioSampleBuffer.cpp @@ -80,7 +80,19 @@ AudioSampleBuffer::AudioSampleBuffer (float** dataToReferTo, allocatedBytes (0) { jassert (numChannels_ > 0); - allocateChannels (dataToReferTo); + allocateChannels (dataToReferTo, 0); +} + +AudioSampleBuffer::AudioSampleBuffer (float** dataToReferTo, + const int numChannels_, + const int startSample, + const int numSamples) throw() + : numChannels (numChannels_), + size (numSamples), + allocatedBytes (0) +{ + jassert (numChannels_ > 0); + allocateChannels (dataToReferTo, startSample); } void AudioSampleBuffer::setDataToReferTo (float** dataToReferTo, @@ -95,10 +107,10 @@ void AudioSampleBuffer::setDataToReferTo (float** dataToReferTo, numChannels = newNumChannels; size = newNumSamples; - allocateChannels (dataToReferTo); + allocateChannels (dataToReferTo, 0); } -void AudioSampleBuffer::allocateChannels (float** const dataToReferTo) +void AudioSampleBuffer::allocateChannels (float** const dataToReferTo, int offset) { // (try to avoid doing a malloc here, as that'll blow up things like Pro-Tools) if (numChannels < numElementsInArray (preallocatedChannelSpace)) @@ -116,7 +128,7 @@ void AudioSampleBuffer::allocateChannels (float** const dataToReferTo) // you have to pass in the same number of valid pointers as numChannels jassert (dataToReferTo[i] != 0); - channels[i] = dataToReferTo[i]; + channels[i] = dataToReferTo[i] + offset; } channels [numChannels] = 0; diff --git a/src/audio/dsp/juce_AudioSampleBuffer.h b/src/audio/dsp/juce_AudioSampleBuffer.h index 0aada2b5f9..d07812a06b 100644 --- a/src/audio/dsp/juce_AudioSampleBuffer.h +++ b/src/audio/dsp/juce_AudioSampleBuffer.h @@ -70,6 +70,27 @@ public: int numChannels, int numSamples) throw(); + /** Creates a buffer using a pre-allocated block of memory. + + Note that if the buffer is resized or its number of channels is changed, it + will re-allocate memory internally and copy the existing data to this new area, + so it will then stop directly addressing this memory. + + @param dataToReferTo a pre-allocated array containing pointers to the data + for each channel that should be used by this buffer. The + buffer will only refer to this memory, it won't try to delete + it when the buffer is deleted or resized. + @param numChannels the number of channels to use - this must correspond to the + number of elements in the array passed in + @param startSample the offset within the arrays at which the data begins + @param numSamples the number of samples to use - this must correspond to the + size of the arrays passed in + */ + AudioSampleBuffer (float** dataToReferTo, + int numChannels, + int startSample, + int numSamples) throw(); + /** Copies another buffer. This buffer will make its own copy of the other's data, unless the buffer was created @@ -429,7 +450,7 @@ private: float* preallocatedChannelSpace [32]; void allocateData(); - void allocateChannels (float** dataToReferTo); + void allocateChannels (float** dataToReferTo, int offset); JUCE_LEAK_DETECTOR (AudioSampleBuffer); }; diff --git a/src/core/juce_StandardHeader.h b/src/core/juce_StandardHeader.h index bca2a4b1ed..7a43ba3425 100644 --- a/src/core/juce_StandardHeader.h +++ b/src/core/juce_StandardHeader.h @@ -33,7 +33,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 53 -#define JUCE_BUILDNUMBER 24 +#define JUCE_BUILDNUMBER 25 /** Current Juce version number. diff --git a/src/core/juce_TargetPlatform.h b/src/core/juce_TargetPlatform.h index 19512ec514..98742185a4 100644 --- a/src/core/juce_TargetPlatform.h +++ b/src/core/juce_TargetPlatform.h @@ -43,6 +43,9 @@ #if (defined (_WIN32) || defined (_WIN64)) #define JUCE_WIN32 1 #define JUCE_WINDOWS 1 +#elif defined (JUCE_ANDROID) + #undef JUCE_ANDROID + #define JUCE_ANDROID 1 #elif defined (LINUX) || defined (__linux__) #define JUCE_LINUX 1 #elif defined (__APPLE_CPP__) || defined(__APPLE_CC__) @@ -54,9 +57,6 @@ #else #define JUCE_MAC 1 #endif -#elif defined (JUCE_ANDROID) - #undef JUCE_ANDROID - #define JUCE_ANDROID 1 #else #error "Unknown platform!" #endif diff --git a/src/gui/components/controls/juce_TextEditor.cpp b/src/gui/components/controls/juce_TextEditor.cpp index d053ddb875..b498755075 100644 --- a/src/gui/components/controls/juce_TextEditor.cpp +++ b/src/gui/components/controls/juce_TextEditor.cpp @@ -310,7 +310,7 @@ private: } else { - while (! text.isEmpty() || text.isWhitespace()) + while (! (text.isEmpty() || text.isWhitespace())) { ++text; ++numChars; diff --git a/src/gui/graphics/colour/juce_Colour.cpp b/src/gui/graphics/colour/juce_Colour.cpp index 6b1767cfc4..3abc6a9f75 100644 --- a/src/gui/graphics/colour/juce_Colour.cpp +++ b/src/gui/graphics/colour/juce_Colour.cpp @@ -54,23 +54,19 @@ namespace ColourHelpers else { s = jmin (1.0f, s); - h = jlimit (0.0f, 1.0f, h); h = (h - std::floor (h)) * 6.0f + 0.00001f; // need a small adjustment to compensate for rounding errors const float f = h - std::floor (h); - const uint8 x = (uint8) roundToInt (v * (1.0f - s)); - const float y = v * (1.0f - s * f); - const float z = v * (1.0f - (s * (1.0f - f))); if (h < 1.0f) { r = intV; - g = (uint8) roundToInt (z); + g = (uint8) roundToInt (v * (1.0f - (s * (1.0f - f)))); b = x; } else if (h < 2.0f) { - r = (uint8) roundToInt (y); + r = (uint8) roundToInt (v * (1.0f - s * f)); g = intV; b = x; } @@ -78,31 +74,25 @@ namespace ColourHelpers { r = x; g = intV; - b = (uint8) roundToInt (z); + b = (uint8) roundToInt (v * (1.0f - (s * (1.0f - f)))); } else if (h < 4.0f) { r = x; - g = (uint8) roundToInt (y); + g = (uint8) roundToInt (v * (1.0f - s * f)); b = intV; } else if (h < 5.0f) { - r = (uint8) roundToInt (z); + r = (uint8) roundToInt (v * (1.0f - (s * (1.0f - f)))); g = x; b = intV; } - else if (h < 6.0f) + else { r = intV; g = x; - b = (uint8) roundToInt (y); - } - else - { - r = 0; - g = 0; - b = 0; + b = (uint8) roundToInt (v * (1.0f - s * f)); } } } @@ -192,7 +182,7 @@ Colour::Colour (const float hue, const float brightness, const float alpha) throw() { - uint8 r = getRed(), g = getGreen(), b = getBlue(); + uint8 r, g, b; ColourHelpers::convertHSBtoRGB (hue, saturation, brightness, r, g, b); argb.setARGB (ColourHelpers::floatAlphaToInt (alpha), r, g, b); @@ -211,7 +201,7 @@ Colour::Colour (const float hue, const float brightness, const uint8 alpha) throw() { - uint8 r = getRed(), g = getGreen(), b = getBlue(); + uint8 r, g, b; ColourHelpers::convertHSBtoRGB (hue, saturation, brightness, r, g, b); argb.setARGB (alpha, r, g, b); @@ -404,10 +394,7 @@ const Colour Colour::withRotatedHue (const float amountToRotate) const throw() float h, s, b; getHSB (h, s, b); - h += amountToRotate; - h -= std::floor (h); - - return Colour (h, s, b, getAlpha()); + return Colour (h + amountToRotate, s, b, getAlpha()); } //============================================================================== diff --git a/src/native/android/juce_android_GraphicsContext.cpp b/src/native/android/juce_android_GraphicsContext.cpp index b8b022d2d5..bd17fae646 100644 --- a/src/native/android/juce_android_GraphicsContext.cpp +++ b/src/native/android/juce_android_GraphicsContext.cpp @@ -33,7 +33,8 @@ class AndroidLowLevelGraphicsContext : public LowLevelGraphicsContext { public: - AndroidLowLevelGraphicsContext() + AndroidLowLevelGraphicsContext (const GlobalRef& canvas_) + : canvas (canvas_) { } @@ -59,12 +60,12 @@ public: bool clipToRectangle (const Rectangle& r) { - return false; + return true; } bool clipToRectangleList (const RectangleList& clipRegion) { - return false; + return true; } void excludeClipRectangle (const Rectangle& r) @@ -86,7 +87,7 @@ public: const Rectangle getClipBounds() const { - return Rectangle(); + return Rectangle (0, 0, 1000, 1000); } bool isClipEmpty() const @@ -113,6 +114,8 @@ public: //============================================================================== void setFill (const FillType& fillType) { + currentPaint = android.env->NewObject (android.paintClass, android.paintClassConstructor); + currentPaint.callVoidMethod (android.setColor, fillType.colour.getARGB()); } void setOpacity (float newOpacity) @@ -126,6 +129,9 @@ public: //============================================================================== void fillRect (const Rectangle& r, bool replaceExistingContents) { + canvas.callVoidMethod (android.drawRect, + (float) r.getX(), (float) r.getY(), (float) r.getRight(), (float) r.getBottom(), + currentPaint.get()); } void fillPath (const Path& path, const AffineTransform& transform) @@ -162,6 +168,8 @@ public: } private: + GlobalRef canvas, currentPaint; + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AndroidLowLevelGraphicsContext); }; diff --git a/src/native/android/juce_android_Misc.cpp b/src/native/android/juce_android_Misc.cpp index 66da48c55c..e17ea1111f 100644 --- a/src/native/android/juce_android_Misc.cpp +++ b/src/native/android/juce_android_Misc.cpp @@ -27,6 +27,42 @@ // compiled on its own). #if JUCE_INCLUDED_FILE +END_JUCE_NAMESPACE +extern JUCE_NAMESPACE::JUCEApplication* juce_CreateApplication(); // (from START_JUCE_APPLICATION) +BEGIN_JUCE_NAMESPACE + +//============================================================================== +JUCE_JNI_CALLBACK (JuceAppActivity, launchApp, void, (JNIEnv* env, jobject activity)) +{ + android.initialise (env, activity); + + JUCEApplication::createInstance = &juce_CreateApplication; + + initialiseJuce_GUI(); + + if (! JUCEApplication::createInstance()->initialiseApp (String::empty)) + exit (0); +} + +JUCE_JNI_CALLBACK (JuceAppActivity, quitApp, void, (JNIEnv* env, jobject activity)) +{ + JUCEApplication::appWillTerminateByForce(); + + android.shutdown(); +} + +//============================================================================== +void PlatformUtilities::beep() +{ + // TODO +} + +//============================================================================== +void Logger::outputDebugString (const String& text) +{ + android.env->CallStaticVoidMethod (android.activityClass, android.printToConsole, + android.javaString (text)); +} //============================================================================== void SystemClipboard::copyTextToClipboard (const String& text) diff --git a/src/native/android/juce_android_NativeCode.cpp b/src/native/android/juce_android_NativeCode.cpp index 519c5cf998..d1964809ea 100644 --- a/src/native/android/juce_android_NativeCode.cpp +++ b/src/native/android/juce_android_NativeCode.cpp @@ -90,11 +90,214 @@ BEGIN_JUCE_NAMESPACE #include "../../containers/juce_ScopedValueSetter.h" #include "../common/juce_MidiDataConcatenator.h" +//============================================================================== +#define JUCE_JNI_CALLBACK(className, methodName, returnType, params) \ + extern "C" __attribute__ ((visibility("default"))) returnType Java_com_juce_ ## className ## _ ## methodName params + +//============================================================================== +#define JUCE_JNI_CLASSES(JAVACLASS) \ + JAVACLASS (activityClass, "com/juce/JuceAppActivity") \ + JAVACLASS (componentPeerViewClass, "com/juce/ComponentPeerView") \ + JAVACLASS (fileClass, "java/io/File") \ + JAVACLASS (contextClass, "android/content/Context") \ + JAVACLASS (canvasClass, "android/graphics/Canvas") \ + JAVACLASS (paintClass, "android/graphics/Paint") \ + + +//============================================================================== +#define JUCE_JNI_METHODS(METHOD, STATICMETHOD) \ +\ + STATICMETHOD (activityClass, printToConsole, "printToConsole", "(Ljava/lang/String;)V") \ + METHOD (activityClass, createNewView, "createNewView", "()Lcom/juce/ComponentPeerView;") \ + METHOD (activityClass, deleteView, "deleteView", "(Lcom/juce/ComponentPeerView;)V") \ +\ + METHOD (fileClass, fileExists, "exists", "()Z") \ +\ + METHOD (componentPeerViewClass, layout, "layout", "(IIII)V") \ +\ + METHOD (canvasClass, drawRect, "drawRect", "(FFFFLandroid/graphics/Paint;)V") \ +\ + METHOD (paintClass, paintClassConstructor, "", "()V") \ + METHOD (paintClass, setColor, "setColor", "(I)V") \ + + +//============================================================================== +class GlobalRef +{ +public: + GlobalRef() + : env (0), obj (0) + { + } + + GlobalRef (JNIEnv* const env_, jobject obj_) + : env (env_), + obj (retain (env_, obj_)) + { + } + + GlobalRef (const GlobalRef& other) + : env (other.env), + obj (retain (other.env, other.obj)) + { + } + + ~GlobalRef() + { + release(); + } + + GlobalRef& operator= (const GlobalRef& other) + { + release(); + env = other.env; + obj = retain (env, other.obj); + return *this; + } + + GlobalRef& operator= (jobject newObj) + { + jassert (env != 0 || newObj == 0); + + if (newObj != obj && env != 0) + { + release(); + obj = retain (env, newObj); + } + } + + inline operator jobject() const throw() { return obj; } + inline jobject get() const throw() { return obj; } + + inline JNIEnv* getEnv() const throw() { return env; } + + #define DECLARE_CALL_TYPE_METHOD(returnType, typeName) \ + returnType call##typeName##Method (jmethodID methodID, ... ) \ + { \ + returnType result; \ + va_list args; \ + va_start (args, methodID); \ + result = env->Call##typeName##MethodV (obj, methodID, args); \ + va_end (args); \ + return result; \ + } + + DECLARE_CALL_TYPE_METHOD (jobject, Object) + DECLARE_CALL_TYPE_METHOD (jboolean, Boolean) + DECLARE_CALL_TYPE_METHOD (jbyte, Byte) + DECLARE_CALL_TYPE_METHOD (jchar, Char) + DECLARE_CALL_TYPE_METHOD (jshort, Short) + DECLARE_CALL_TYPE_METHOD (jint, Int) + DECLARE_CALL_TYPE_METHOD (jlong, Long) + DECLARE_CALL_TYPE_METHOD (jfloat, Float) + DECLARE_CALL_TYPE_METHOD (jdouble, Double) + #undef DECLARE_CALL_TYPE_METHOD + + void callVoidMethod (jmethodID methodID, ... ) + { + va_list args; + va_start (args, methodID); + env->CallVoidMethodV (obj, methodID, args); + va_end (args); + } + +private: + JNIEnv* env; + jobject obj; + + void release() + { + if (env != 0) + env->DeleteGlobalRef (obj); + } + + static jobject retain (JNIEnv* const env, jobject obj_) + { + return env == 0 ? 0 : env->NewGlobalRef (obj_); + } +}; + +//============================================================================== +class AndroidJavaCallbacks +{ +public: + AndroidJavaCallbacks() : env (0) + { + } + + void initialise (JNIEnv* env_, jobject activity_) + { + env = env_; + activity = GlobalRef (env, activity_); + + #define CREATE_JNI_CLASS(className, path) \ + className = (jclass) env->NewGlobalRef (env->FindClass (path)); \ + jassert (className != 0); + JUCE_JNI_CLASSES (CREATE_JNI_CLASS); + #undef CREATE_JNI_CLASS + + #define CREATE_JNI_METHOD(ownerClass, methodID, stringName, params) \ + methodID = env->GetMethodID (ownerClass, stringName, params); \ + jassert (methodID != 0); + #define CREATE_JNI_STATICMETHOD(ownerClass, methodID, stringName, params) \ + methodID = env->GetStaticMethodID (ownerClass, stringName, params); \ + jassert (methodID != 0); + JUCE_JNI_METHODS (CREATE_JNI_METHOD, CREATE_JNI_STATICMETHOD); + #undef CREATE_JNI_METHOD + } + + void shutdown() + { + if (env != 0) + { + #define RELEASE_JNI_CLASS(className, path) env->DeleteGlobalRef (className); + JUCE_JNI_CLASSES (RELEASE_JNI_CLASS); + #undef RELEASE_JNI_CLASS + + activity = 0; + env = 0; + } + } + + //============================================================================== + const String juceString (jstring s) const + { + jboolean isCopy; + const char* const utf8 = env->GetStringUTFChars (s, &isCopy); + CharPointer_UTF8 utf8CP (utf8); + const String result (utf8CP); + env->ReleaseStringUTFChars (s, utf8); + return result; + } + + jstring javaString (const String& s) const + { + return env->NewStringUTF (s.toUTF8()); + } + + //============================================================================== + JNIEnv* env; + GlobalRef activity; + + //============================================================================== + #define DECLARE_JNI_CLASS(className, path) jclass className; + JUCE_JNI_CLASSES (DECLARE_JNI_CLASS); + #undef DECLARE_JNI_CLASS + + #define DECLARE_JNI_METHOD(ownerClass, methodID, stringName, params) jmethodID methodID; + JUCE_JNI_METHODS (DECLARE_JNI_METHOD, DECLARE_JNI_METHOD); + #undef DECLARE_JNI_METHOD +}; + +static AndroidJavaCallbacks android; + + //============================================================================== #define JUCE_INCLUDED_FILE 1 // Now include the actual code files.. -#include "juce_android_SystemStats.cpp" // (must be first) +#include "juce_android_Misc.cpp" +#include "juce_android_SystemStats.cpp" #include "../common/juce_posix_SharedCode.h" #include "juce_android_Files.cpp" #include "../common/juce_posix_NamedPipe.cpp" @@ -105,7 +308,6 @@ BEGIN_JUCE_NAMESPACE #include "juce_android_GraphicsContext.cpp" #include "juce_android_Windowing.cpp" #include "juce_android_FileChooser.cpp" -#include "juce_android_Misc.cpp" #include "juce_android_WebBrowserComponent.cpp" #include "juce_android_OpenGLComponent.cpp" #include "juce_android_Midi.cpp" diff --git a/src/native/android/juce_android_SystemStats.cpp b/src/native/android/juce_android_SystemStats.cpp index a35ac2129e..d6f6144374 100644 --- a/src/native/android/juce_android_SystemStats.cpp +++ b/src/native/android/juce_android_SystemStats.cpp @@ -27,80 +27,6 @@ // compiled on its own). #if JUCE_INCLUDED_FILE -END_JUCE_NAMESPACE -extern JUCE_NAMESPACE::JUCEApplication* juce_CreateApplication(); // (from START_JUCE_APPLICATION) -BEGIN_JUCE_NAMESPACE - -//============================================================================== -class AndroidJavaCallbacks -{ -public: - AndroidJavaCallbacks() : env (0) - { - } - - void initialise (JNIEnv* env_, jobject activity) - { - env = env_; - activityClass = (jclass) env->NewGlobalRef (env->GetObjectClass (activity)); - - printToConsole = env->GetStaticMethodID (activityClass, "printToConsole", "(Ljava/lang/String;)V"); - jassert (printToConsole != 0); - } - - void shutdown() - { - if (env != 0) - { - env->DeleteGlobalRef (activityClass); - } - } - - //============================================================================== - JNIEnv* env; - - jclass activityClass; - jmethodID printToConsole; -}; - -static AndroidJavaCallbacks androidEnv; - -//============================================================================== -#define JUCE_JNI_CALLBACK(className, methodName, returnType, params) \ - extern "C" __attribute__ ((visibility("default"))) returnType Java_com_juce_launch_ ## className ## _ ## methodName params - -//============================================================================== -JUCE_JNI_CALLBACK (JuceAppActivity, launchApp, void, (JNIEnv* env, jobject activity)) -{ - androidEnv.initialise (env, activity); - - JUCEApplication::createInstance = &juce_CreateApplication; - - initialiseJuce_GUI(); - - if (! JUCEApplication::createInstance()->initialiseApp (String::empty)) - exit (0); -} - -JUCE_JNI_CALLBACK (JuceAppActivity, quitApp, void, (JNIEnv* env, jobject activity)) -{ - JUCEApplication::appWillTerminateByForce(); - - androidEnv.shutdown(); -} - -//============================================================================== -void PlatformUtilities::beep() -{ - // TODO -} - -//============================================================================== -void Logger::outputDebugString (const String& text) -{ - androidEnv.env->CallStaticVoidMethod (androidEnv.activityClass, androidEnv.printToConsole, - androidEnv.env->NewStringUTF (text.toUTF8())); -} //============================================================================== SystemStats::OperatingSystemType SystemStats::getOperatingSystemType() diff --git a/src/native/android/juce_android_Windowing.cpp b/src/native/android/juce_android_Windowing.cpp index 2c9cac4671..5dbda28c6a 100644 --- a/src/native/android/juce_android_Windowing.cpp +++ b/src/native/android/juce_android_Windowing.cpp @@ -36,11 +36,13 @@ public: AndroidComponentPeer (Component* const component, const int windowStyleFlags) : ComponentPeer (component, windowStyleFlags) { - // TODO + view = GlobalRef (android.env, android.activity.callObjectMethod (android.createNewView)); } ~AndroidComponentPeer() { + android.activity.callVoidMethod (android.deleteView, view.get()); + view = 0; } void* getNativeHandle() const @@ -67,7 +69,8 @@ public: void setBounds (int x, int y, int w, int h, bool isNowFullScreen) { - // TODO + DBG ("Window size: " << x << " " << y << " " << w << " " << h); + view.callVoidMethod (android.layout, x, y, x + w, y + h); } const Rectangle getBounds() const @@ -167,6 +170,12 @@ public: } //============================================================================== + void handlePaintCallback (JNIEnv* env, jobject canvas) + { + AndroidLowLevelGraphicsContext g (GlobalRef (env, canvas)); + handlePaint (g); + } + void repaint (const Rectangle& area) { // TODO @@ -182,14 +191,42 @@ public: // TODO } + //============================================================================== + static AndroidComponentPeer* findPeerForJavaView (jobject viewToFind) + { + for (int i = getNumPeers(); --i >= 0;) + { + AndroidComponentPeer* const ap = static_cast (getPeer(i)); + jassert (dynamic_cast (getPeer(i)) != 0); + + if (ap->view == viewToFind) + return ap; + } + + return 0; + } + private: //============================================================================== - + GlobalRef view; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AndroidComponentPeer); }; +//============================================================================== +#define JUCE_VIEW_CALLBACK(returnType, javaMethodName, params, juceMethodInvocation) \ + JUCE_JNI_CALLBACK (ComponentPeerView, javaMethodName, returnType, params) \ + { \ + AndroidComponentPeer* const peer = AndroidComponentPeer::findPeerForJavaView (view); \ + if (peer != 0) \ + peer->juceMethodInvocation; \ + } +JUCE_VIEW_CALLBACK (void, handlePaint, (JNIEnv* env, jobject view, jobject canvas), + handlePaintCallback (env, canvas)) + + +//============================================================================== ComponentPeer* Component::createNewPeer (int styleFlags, void*) { return new AndroidComponentPeer (this, styleFlags); @@ -282,11 +319,17 @@ void juce_setKioskComponent (Component* kioskModeComponent, bool enableOrDisable } //============================================================================== +static int screenWidth = 0, screenHeight = 0; + void juce_updateMultiMonitorInfo (Array >& monitorCoords, const bool clipToWorkArea) { - // TODO + monitorCoords.add (Rectangle (0, 0, screenWidth, screenHeight)); +} - monitorCoords.add (Rectangle (0, 0, 640, 480)); +JUCE_JNI_CALLBACK (JuceAppActivity, setScreenSize, void, (JNIEnv* env, jobject activity, int w, int h)) +{ + screenWidth = w; + screenHeight = h; } //==============================================================================