| @@ -52,11 +52,15 @@ public: | |||
| @param exitCallback A callback which will be called when the modal | |||
| bluetooth dialog is closed. | |||
| @param btWindowBounds The bounds of the bluetooth window that will | |||
| be opened. The dialog itself is opened by the OS so cannot | |||
| be customised by JUCE. | |||
| @return true if the dialogue was opened, false on error. | |||
| @see ModalComponentManager::Callback | |||
| */ | |||
| static bool open (ModalComponentManager::Callback* exitCallback = nullptr); | |||
| static bool open (ModalComponentManager::Callback* exitCallback = nullptr, | |||
| Rectangle<int>* btWindowBounds = nullptr); | |||
| /** Checks if a Bluetooth MIDI pairing dialogue is available on this | |||
| platform. | |||
| @@ -391,7 +391,9 @@ private: | |||
| class BluetoothMidiSelectorOverlay : public Component | |||
| { | |||
| public: | |||
| BluetoothMidiSelectorOverlay (ModalComponentManager::Callback* exitCallbackToUse) | |||
| BluetoothMidiSelectorOverlay (ModalComponentManager::Callback* exitCallbackToUse, | |||
| const Rectangle<int>& boundsToUse) | |||
| : bounds (boundsToUse) | |||
| { | |||
| ScopedPointer<ModalComponentManager::Callback> exitCallback (exitCallbackToUse); | |||
| @@ -400,8 +402,14 @@ public: | |||
| setAlwaysOnTop (true); | |||
| setVisible (true); | |||
| addToDesktop (ComponentPeer::windowHasDropShadow); | |||
| setBounds (0, 0, getParentWidth(), getParentHeight()); | |||
| if (bounds.isEmpty()) | |||
| setBounds (0, 0, getParentWidth(), getParentHeight()); | |||
| else | |||
| setBounds (bounds); | |||
| toFront (true); | |||
| setOpaque (! bounds.isEmpty()); | |||
| addAndMakeVisible (bluetoothDevicesList); | |||
| enterModalState (true, exitCallback.release(), true); | |||
| @@ -414,7 +422,7 @@ public: | |||
| void paint (Graphics& g) override | |||
| { | |||
| g.fillAll (Colours::black.withAlpha (0.6f)); | |||
| g.fillAll (bounds.isEmpty() ? Colours::black.withAlpha (0.6f) : Colours::black); | |||
| g.setColour (Colour (0xffdfdfdf)); | |||
| Rectangle<int> overlayBounds = getOverlayBounds(); | |||
| @@ -441,19 +449,30 @@ public: | |||
| void parentSizeChanged() override { update(); } | |||
| private: | |||
| Rectangle<int> bounds; | |||
| void update() | |||
| { | |||
| setBounds (0, 0, getParentWidth(), getParentHeight()); | |||
| if (bounds.isEmpty()) | |||
| setBounds (0, 0, getParentWidth(), getParentHeight()); | |||
| else | |||
| setBounds (bounds); | |||
| bluetoothDevicesList.setBounds (getOverlayBounds().withTrimmedTop (40)); | |||
| } | |||
| Rectangle<int> getOverlayBounds() const noexcept | |||
| { | |||
| const int pw = getParentWidth(); | |||
| const int ph = getParentHeight(); | |||
| if (bounds.isEmpty()) | |||
| { | |||
| const int pw = getParentWidth(); | |||
| const int ph = getParentHeight(); | |||
| return Rectangle<int> (pw, ph).withSizeKeepingCentre (jmin (400, pw - 14), | |||
| jmin (300, ph - 40)); | |||
| } | |||
| return Rectangle<int> (pw, ph).withSizeKeepingCentre (jmin (400, pw - 14), | |||
| jmin (300, ph - 40)); | |||
| return bounds.withZeroOrigin(); | |||
| } | |||
| AndroidBluetoothMidiDevicesListBox bluetoothDevicesList; | |||
| @@ -462,9 +481,11 @@ private: | |||
| }; | |||
| //============================================================================== | |||
| bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallbackPtr) | |||
| bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallbackPtr, | |||
| Rectangle<int>* btBounds) | |||
| { | |||
| ScopedPointer<ModalComponentManager::Callback> exitCallback (exitCallbackPtr); | |||
| auto boundsToUse = (btBounds != nullptr ? *btBounds : Rectangle<int> {}); | |||
| if (! RuntimePermissions::isGranted (RuntimePermissions::bluetoothMidi)) | |||
| { | |||
| @@ -475,7 +496,7 @@ bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* | |||
| return false; | |||
| } | |||
| new BluetoothMidiSelectorOverlay (exitCallback.release()); | |||
| new BluetoothMidiSelectorOverlay (exitCallback.release(), boundsToUse); | |||
| return true; | |||
| } | |||
| @@ -40,15 +40,23 @@ namespace juce | |||
| class BluetoothMidiSelectorOverlay : public Component | |||
| { | |||
| public: | |||
| BluetoothMidiSelectorOverlay (ModalComponentManager::Callback* exitCallbackToUse) | |||
| BluetoothMidiSelectorOverlay (ModalComponentManager::Callback* exitCallbackToUse, | |||
| const Rectangle<int>& boundsToUse) | |||
| : bounds (boundsToUse) | |||
| { | |||
| ScopedPointer<ModalComponentManager::Callback> exitCallback (exitCallbackToUse); | |||
| setAlwaysOnTop (true); | |||
| setVisible (true); | |||
| addToDesktop (ComponentPeer::windowHasDropShadow); | |||
| setBounds (0, 0, getParentWidth(), getParentHeight()); | |||
| if (bounds.isEmpty()) | |||
| setBounds (0, 0, getParentWidth(), getParentHeight()); | |||
| else | |||
| setBounds (bounds); | |||
| toFront (true); | |||
| setOpaque (! bounds.isEmpty()); | |||
| controller = [[CABTMIDICentralViewController alloc] init]; | |||
| nativeSelectorComponent.setView ([controller view]); | |||
| @@ -66,7 +74,7 @@ public: | |||
| void paint (Graphics& g) override | |||
| { | |||
| g.fillAll (Colours::black.withAlpha (0.5f)); | |||
| g.fillAll (bounds.isEmpty() ? Colours::black.withAlpha (0.5f) : Colours::black); | |||
| } | |||
| void inputAttemptWhenModal() override { close(); } | |||
| @@ -78,12 +86,19 @@ public: | |||
| private: | |||
| void update() | |||
| { | |||
| const int pw = getParentWidth(); | |||
| const int ph = getParentHeight(); | |||
| nativeSelectorComponent.setBounds (Rectangle<int> (pw, ph) | |||
| .withSizeKeepingCentre (jmin (400, pw), | |||
| jmin (450, ph - 40))); | |||
| if (bounds.isEmpty()) | |||
| { | |||
| const int pw = getParentWidth(); | |||
| const int ph = getParentHeight(); | |||
| nativeSelectorComponent.setBounds (Rectangle<int> (pw, ph) | |||
| .withSizeKeepingCentre (jmin (400, pw), | |||
| jmin (450, ph - 40))); | |||
| } | |||
| else | |||
| { | |||
| nativeSelectorComponent.setBounds (bounds.withZeroOrigin()); | |||
| } | |||
| } | |||
| void close() | |||
| @@ -94,17 +109,20 @@ private: | |||
| CABTMIDICentralViewController* controller; | |||
| UIViewComponent nativeSelectorComponent; | |||
| Rectangle<int> bounds; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BluetoothMidiSelectorOverlay) | |||
| }; | |||
| bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallback) | |||
| bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallback, | |||
| Rectangle<int>* btBounds) | |||
| { | |||
| ScopedPointer<ModalComponentManager::Callback> cb (exitCallback); | |||
| auto boundsToUse = (btBounds != nullptr ? *btBounds : Rectangle<int> {}); | |||
| if (isAvailable()) | |||
| { | |||
| new BluetoothMidiSelectorOverlay (cb.release()); | |||
| new BluetoothMidiSelectorOverlay (cb.release(), boundsToUse); | |||
| return true; | |||
| } | |||
| @@ -123,7 +141,8 @@ bool BluetoothMidiDevicePairingDialogue::isAvailable() | |||
| namespace juce | |||
| { | |||
| bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallback) | |||
| bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallback, | |||
| Rectangle<int>*) | |||
| { | |||
| ScopedPointer<ModalComponentManager::Callback> cb (exitCallback); | |||
| return false; | |||
| @@ -27,7 +27,8 @@ | |||
| namespace juce | |||
| { | |||
| bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallback) | |||
| bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallback, | |||
| Rectangle<int>*) | |||
| { | |||
| ScopedPointer<ModalComponentManager::Callback> cb (exitCallback); | |||
| // not implemented on Linux yet! | |||
| @@ -27,7 +27,8 @@ | |||
| namespace juce | |||
| { | |||
| bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallback) | |||
| bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallback, | |||
| Rectangle<int>*) | |||
| { | |||
| ScopedPointer<ModalComponentManager::Callback> cb (exitCallback); | |||
| // Do not call this on OSX. Instead, you should pair Bluetooth MIDI devices | |||
| @@ -27,7 +27,8 @@ | |||
| namespace juce | |||
| { | |||
| bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallback) | |||
| bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallback, | |||
| Rectangle<int>*) | |||
| { | |||
| ScopedPointer<ModalComponentManager::Callback> cb (exitCallback); | |||
| // not implemented on Windows yet! | |||