kopia lustrzana https://github.com/jameshball/osci-render
Add popout button to sosci
rodzic
ddd2163644
commit
3580ef5fa4
|
@ -25,7 +25,7 @@ void AudioBackgroundThreadManager::write(const OsciPoint& point) {
|
|||
void AudioBackgroundThreadManager::write(const OsciPoint& point, juce::String name) {
|
||||
juce::SpinLock::ScopedLockType scope(lock);
|
||||
for (auto& thread : threads) {
|
||||
if (thread->getThreadName() == name) {
|
||||
if (thread->getThreadName().contains(name)) {
|
||||
thread->write(point);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,8 +13,19 @@ TextParser::~TextParser() {
|
|||
void TextParser::parse(juce::String text, juce::Font font) {
|
||||
lastFont = font;
|
||||
|
||||
// Apply formatting markers if the font is bold or italic
|
||||
juce::String formattedText = text;
|
||||
|
||||
if (font.isBold()) {
|
||||
formattedText = "*" + formattedText + "*";
|
||||
}
|
||||
|
||||
if (font.isItalic()) {
|
||||
formattedText = "_" + formattedText + "_";
|
||||
}
|
||||
|
||||
// Parse the text with formatting
|
||||
attributedString = parseFormattedText(text, font);
|
||||
attributedString = parseFormattedText(formattedText, font);
|
||||
|
||||
// Create a TextLayout from the AttributedString
|
||||
juce::TextLayout layout;
|
||||
|
|
|
@ -80,7 +80,7 @@ VisualiserComponent::VisualiserComponent(
|
|||
addAndMakeVisible(fullScreenButton);
|
||||
fullScreenButton.setTooltip("Toggles fullscreen mode.");
|
||||
}
|
||||
if (child == nullptr && parent == nullptr && !visualiserOnly) {
|
||||
if (child == nullptr && parent == nullptr) {
|
||||
addAndMakeVisible(popOutButton);
|
||||
popOutButton.setTooltip("Opens the oscilloscope in a new window.");
|
||||
}
|
||||
|
@ -315,11 +315,13 @@ double VisualiserComponent::getSweepIncrement() {
|
|||
return 1.0 / (sampleRate * settings.getSweepSeconds());
|
||||
}
|
||||
|
||||
void VisualiserComponent::setPaused(bool paused) {
|
||||
void VisualiserComponent::setPaused(bool paused, bool affectAudio) {
|
||||
active = !paused;
|
||||
setShouldBeRunning(active);
|
||||
renderingSemaphore.release();
|
||||
audioPlayer.setPaused(paused);
|
||||
if (affectAudio) {
|
||||
audioPlayer.setPaused(paused);
|
||||
}
|
||||
repaint();
|
||||
}
|
||||
|
||||
|
@ -334,7 +336,8 @@ void VisualiserComponent::mouseMove(const juce::MouseEvent& event) {
|
|||
hideButtonRow = false;
|
||||
setMouseCursor(juce::MouseCursor::PointingHandCursor);
|
||||
|
||||
if (fullScreen) {
|
||||
// Treat both fullScreen mode and pop-out mode (parent != nullptr) as needing auto-hide controls
|
||||
if (fullScreen || parent != nullptr) {
|
||||
if (!getScreenBounds().removeFromBottom(25).contains(event.getScreenX(), event.getScreenY()) && !event.mods.isLeftButtonDown()) {
|
||||
lastMouseX = event.getScreenX();
|
||||
lastMouseY = event.getScreenY();
|
||||
|
@ -348,7 +351,8 @@ void VisualiserComponent::mouseMove(const juce::MouseEvent& event) {
|
|||
juce::Timer::callAfterDelay(1000, [this, weakRef, newTimerId, pos, parent]() {
|
||||
if (weakRef) {
|
||||
if (parent == nullptr || parent->child == this) {
|
||||
if (timerId == newTimerId && fullScreen) {
|
||||
// Check both fullscreen or pop-out mode
|
||||
if (timerId == newTimerId && (fullScreen || this->parent != nullptr)) {
|
||||
hideButtonRow = true;
|
||||
setMouseCursor(juce::MouseCursor::NoCursor);
|
||||
resized();
|
||||
|
@ -545,7 +549,8 @@ void VisualiserComponent::setRecording(bool recording) {
|
|||
|
||||
void VisualiserComponent::resized() {
|
||||
auto area = getLocalBounds();
|
||||
if (fullScreen && hideButtonRow) {
|
||||
// Apply hideButtonRow logic to both fullscreen and pop-out modes
|
||||
if ((fullScreen || parent != nullptr) && hideButtonRow) {
|
||||
buttonRow = area.removeFromBottom(0);
|
||||
} else {
|
||||
buttonRow = area.removeFromBottom(25);
|
||||
|
@ -554,7 +559,7 @@ void VisualiserComponent::resized() {
|
|||
if (parent == nullptr) {
|
||||
fullScreenButton.setBounds(buttons.removeFromRight(30));
|
||||
}
|
||||
if (child == nullptr && parent == nullptr && !visualiserOnly) {
|
||||
if (child == nullptr && parent == nullptr) {
|
||||
popOutButton.setBounds(buttons.removeFromRight(30));
|
||||
}
|
||||
if (openSettings != nullptr) {
|
||||
|
@ -563,12 +568,15 @@ void VisualiserComponent::resized() {
|
|||
} else {
|
||||
settingsButton.setVisible(false);
|
||||
}
|
||||
if (visualiserOnly && juce::JUCEApplication::isStandaloneApp()) {
|
||||
|
||||
if (visualiserOnly && juce::JUCEApplication::isStandaloneApp() && child == nullptr) {
|
||||
audioInputButton.setBounds(buttons.removeFromRight(30));
|
||||
}
|
||||
|
||||
#if SOSCI_FEATURES
|
||||
sharedTextureButton.setBounds(buttons.removeFromRight(30));
|
||||
#endif
|
||||
|
||||
record.setBounds(buttons.removeFromRight(25));
|
||||
if (record.getToggleState()) {
|
||||
stopwatch.setVisible(true);
|
||||
|
@ -576,14 +584,20 @@ void VisualiserComponent::resized() {
|
|||
} else {
|
||||
stopwatch.setVisible(false);
|
||||
}
|
||||
|
||||
#if SOSCI_FEATURES
|
||||
if (child == nullptr && downloading) {
|
||||
auto bounds = buttons.removeFromRight(160);
|
||||
ffmpegDownloader.setBounds(bounds.withSizeKeepingCentre(bounds.getWidth() - 10, bounds.getHeight() - 10));
|
||||
}
|
||||
#endif
|
||||
|
||||
buttons.removeFromRight(10); // padding
|
||||
audioPlayer.setBounds(buttons);
|
||||
|
||||
if (child == nullptr) {
|
||||
audioPlayer.setBounds(buttons);
|
||||
}
|
||||
|
||||
viewportArea = area;
|
||||
viewportChanged(viewportArea);
|
||||
}
|
||||
|
@ -603,21 +617,23 @@ void VisualiserComponent::popoutWindow() {
|
|||
ffmpegFile,
|
||||
settings,
|
||||
recordingSettings,
|
||||
this
|
||||
this,
|
||||
visualiserOnly
|
||||
);
|
||||
visualiser->settings.setLookAndFeel(&getLookAndFeel());
|
||||
visualiser->openSettings = openSettings;
|
||||
visualiser->closeSettings = closeSettings;
|
||||
// Pop-out visualiser is created with parent set to this component
|
||||
child = visualiser;
|
||||
childUpdated();
|
||||
visualiser->setSize(300, 325);
|
||||
visualiser->setSize(350, 350);
|
||||
popout = std::make_unique<VisualiserWindow>("Software Oscilloscope", this);
|
||||
popout->setContentOwned(visualiser, true);
|
||||
popout->setUsingNativeTitleBar(true);
|
||||
popout->setResizable(true, false);
|
||||
popout->setVisible(true);
|
||||
popout->centreWithSize(300, 325);
|
||||
setPaused(true);
|
||||
popout->centreWithSize(350, 350);
|
||||
setPaused(true, false);
|
||||
resized();
|
||||
}
|
||||
|
||||
|
@ -627,12 +643,14 @@ void VisualiserComponent::childUpdated() {
|
|||
ffmpegDownloader.setVisible(child == nullptr);
|
||||
#endif
|
||||
record.setVisible(child == nullptr);
|
||||
audioPlayer.setVisible(child == nullptr);
|
||||
if (child != nullptr) {
|
||||
audioProcessor.haltRecording = [this] {
|
||||
setRecording(false);
|
||||
child->setRecording(false);
|
||||
};
|
||||
} else {
|
||||
audioPlayer.setup();
|
||||
audioProcessor.haltRecording = [this] {
|
||||
setRecording(false);
|
||||
};
|
||||
|
|
|
@ -60,7 +60,7 @@ public:
|
|||
int prepareTask(double sampleRate, int samplesPerBlock) override;
|
||||
void runTask(const std::vector<OsciPoint>& points) override;
|
||||
void stopTask() override;
|
||||
void setPaused(bool paused);
|
||||
void setPaused(bool paused, bool affectAudio = true);
|
||||
void mouseDrag(const juce::MouseEvent& event) override;
|
||||
void mouseMove(const juce::MouseEvent& event) override;
|
||||
void mouseDown(const juce::MouseEvent& event) override;
|
||||
|
@ -292,11 +292,13 @@ public:
|
|||
}
|
||||
|
||||
void closeButtonPressed() override {
|
||||
// local copy of parent so that we can safely delete the child
|
||||
VisualiserComponent* parent = this->parent;
|
||||
parent->setPaused(wasPaused);
|
||||
parent->child = nullptr;
|
||||
parent->popout.reset();
|
||||
parent->childUpdated();
|
||||
parent->resized();
|
||||
parent->popout.reset();
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
Ładowanie…
Reference in New Issue