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