Add pop-up window for visualiser

pull/245/head v2.2.0
James H Ball 2024-06-02 20:56:33 +01:00 zatwierdzone przez James H Ball
rodzic 063b33e956
commit 4515e3a153
2 zmienionych plików z 94 dodań i 25 usunięć

Wyświetl plik

@ -1,7 +1,7 @@
#include "VisualiserComponent.h"
#include "../LookAndFeel.h"
VisualiserComponent::VisualiserComponent(int numChannels, OscirenderAudioProcessor& p) : numChannels(numChannels), backgroundColour(juce::Colours::black), waveformColour(juce::Colour(0xff00ff00)), audioProcessor(p), juce::Thread("VisualiserComponent") {
VisualiserComponent::VisualiserComponent(int numChannels, OscirenderAudioProcessor& p, VisualiserComponent* parent) : numChannels(numChannels), backgroundColour(juce::Colours::black), waveformColour(juce::Colour(0xff00ff00)), audioProcessor(p), juce::Thread("VisualiserComponent"), parent(parent) {
resetBuffer();
startTimerHz(60);
startThread();
@ -20,7 +20,12 @@ VisualiserComponent::VisualiserComponent(int numChannels, OscirenderAudioProcess
setMouseCursor(juce::MouseCursor::PointingHandCursor);
setWantsKeyboardFocus(true);
addChildComponent(fullScreenButton);
if (parent == nullptr) {
addChildComponent(fullScreenButton);
}
if (child == nullptr && parent == nullptr) {
addChildComponent(popOutButton);
}
addChildComponent(settingsButton);
fullScreenButton.onClick = [this]() {
@ -35,6 +40,21 @@ VisualiserComponent::VisualiserComponent(int numChannels, OscirenderAudioProcess
menu.showMenuAsync(juce::PopupMenu::Options(), [this](int result) {});
};
popOutButton.onClick = [this, numChannels]() {
auto visualiser = new VisualiserComponent(numChannels, audioProcessor, this);
child = visualiser;
popOutButton.setVisible(false);
visualiser->setSize(300, 300);
popout = std::make_unique<VisualiserWindow>("Software Oscilloscope", this);
popout->setContentOwned(visualiser, true);
popout->setUsingNativeTitleBar(true);
popout->setResizable(true, false);
popout->setVisible(true);
setPaused(true);
resized();
popOutButton.setVisible(false);
};
}
VisualiserComponent::~VisualiserComponent() {
@ -94,7 +114,8 @@ void VisualiserComponent::paint(juce::Graphics& g) {
// add text
g.setColour(juce::Colours::white);
g.setFont(14.0f);
g.drawFittedText("Paused", getLocalBounds(), juce::Justification::centred, 1);
auto text = child != nullptr ? "Open in separate window" : "Paused";
g.drawFittedText(text, getLocalBounds(), juce::Justification::centred, 1);
}
}
@ -114,18 +135,22 @@ void VisualiserComponent::run() {
}
}
void VisualiserComponent::setPaused(bool paused) {
active = !paused;
if (active) {
startTimerHz(60);
startThread();
} else {
audioProcessor.consumerStop(consumer);
stopTimer();
stopThread(1000);
}
repaint();
}
void VisualiserComponent::mouseDown(const juce::MouseEvent& event) {
if (event.mods.isLeftButtonDown()) {
active = !active;
if (active) {
startTimerHz(60);
startThread();
} else {
audioProcessor.consumerStop(consumer);
stopTimer();
stopThread(1000);
}
repaint();
if (event.mods.isLeftButtonDown() && child == nullptr) {
setPaused(active);
}
}
@ -138,16 +163,31 @@ void VisualiserComponent::mouseMove(const juce::MouseEvent& event) {
int newTimerId = juce::Random::getSystemRandom().nextInt();
timerId = newTimerId;
fullScreenButton.setVisible(true);
if (parent == nullptr) {
fullScreenButton.setVisible(true);
}
if (child == nullptr && parent == nullptr) {
popOutButton.setVisible(true);
}
settingsButton.setVisible(true);
auto pos = event.getScreenPosition();
auto parent = this->parent;
juce::Timer::callAfterDelay(1000, [this, newTimerId, pos]() {
bool onButtonRow = fullScreenButton.getScreenBounds().contains(pos) || settingsButton.getScreenBounds().contains(pos);
if (timerId == newTimerId && !onButtonRow) {
fullScreenButton.setVisible(false);
settingsButton.setVisible(false);
repaint();
juce::Timer::callAfterDelay(1000, [this, newTimerId, pos, parent]() {
if (parent == nullptr || parent->child == this) {
bool onButtonRow = settingsButton.getScreenBounds().contains(pos);
if (parent == nullptr) {
onButtonRow |= fullScreenButton.getScreenBounds().contains(pos);
}
if (child == nullptr && parent == nullptr) {
onButtonRow |= popOutButton.getScreenBounds().contains(pos);
}
if (timerId == newTimerId && !onButtonRow) {
fullScreenButton.setVisible(false);
popOutButton.setVisible(false);
settingsButton.setVisible(false);
repaint();
}
}
});
repaint();
@ -227,6 +267,12 @@ void VisualiserComponent::resized() {
auto area = getLocalBounds();
area.removeFromBottom(5);
auto buttonRow = area.removeFromBottom(25);
fullScreenButton.setBounds(buttonRow.removeFromRight(30));
if (parent == nullptr) {
fullScreenButton.setBounds(buttonRow.removeFromRight(30));
}
if (child == nullptr && parent == nullptr) {
popOutButton.setBounds(buttonRow.removeFromRight(30));
}
settingsButton.setBounds(buttonRow.removeFromRight(30));
}

Wyświetl plik

@ -13,9 +13,10 @@ enum class FullScreenMode {
MAIN_COMPONENT,
};
class VisualiserWindow;
class VisualiserComponent : public juce::Component, public juce::Timer, public juce::Thread, public juce::MouseListener, public juce::SettableTooltipClient {
public:
VisualiserComponent(int numChannels, OscirenderAudioProcessor& p);
VisualiserComponent(int numChannels, OscirenderAudioProcessor& p, VisualiserComponent* parent = nullptr);
~VisualiserComponent() override;
void enableFullScreen();
@ -29,16 +30,23 @@ public:
void resized() override;
void timerCallback() override;
void run() override;
void setPaused(bool paused);
void mouseDown(const juce::MouseEvent& event) override;
void mouseMove(const juce::MouseEvent& event) override;
bool keyPressed(const juce::KeyPress& key) override;
void setFullScreen(bool fullScreen);
VisualiserComponent* parent = nullptr;
VisualiserComponent* child = nullptr;
std::unique_ptr<VisualiserWindow> popout = nullptr;
std::atomic<bool> active = true;
private:
const double BUFFER_LENGTH_SECS = 0.02;
const double DEFAULT_SAMPLE_RATE = 192000.0;
std::atomic<int> timerId;
std::atomic<int> lastMouseX;
@ -55,12 +63,11 @@ private:
LabelledTextBox intensity{"Intensity", 0, 1, 0.01};
SvgButton fullScreenButton{ "fullScreen", BinaryData::fullscreen_svg, juce::Colours::white, juce::Colours::white };
SvgButton popOutButton{ "popOut", BinaryData::open_in_new_svg, juce::Colours::white, juce::Colours::white };
SvgButton settingsButton{ "settings", BinaryData::cog_svg, juce::Colours::white, juce::Colours::white };
std::vector<float> tempBuffer;
int precision = 4;
std::atomic<bool> active = true;
std::shared_ptr<BufferConsumer> consumer;
@ -70,3 +77,19 @@ private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VisualiserComponent)
};
class VisualiserWindow : public juce::DocumentWindow {
public:
VisualiserWindow(juce::String name, VisualiserComponent* parent) : parent(parent), wasPaused(!parent->active), juce::DocumentWindow(name, juce::Colours::black, juce::DocumentWindow::TitleBarButtons::allButtons) {}
void closeButtonPressed() override {
parent->setPaused(wasPaused);
parent->child = nullptr;
parent->resized();
parent->popout.reset();
}
private:
VisualiserComponent* parent;
bool wasPaused;
};