From 902286a086e72c536963c8ae9b013f2a7c29df56 Mon Sep 17 00:00:00 2001 From: James Ball Date: Sun, 2 Jul 2023 13:09:24 +0100 Subject: [PATCH] All files have their own code editors, fix various bugs --- Source/MainComponent.cpp | 6 ++ Source/MainComponent.h | 3 +- Source/PluginEditor.cpp | 134 ++++++++++++++++++++-------------- Source/PluginEditor.h | 9 ++- Source/PluginProcessor.cpp | 8 ++ Source/PluginProcessor.h | 1 + Source/parser/FrameProducer.h | 2 +- 7 files changed, 103 insertions(+), 60 deletions(-) diff --git a/Source/MainComponent.cpp b/Source/MainComponent.cpp index a357d28..cd7ceb2 100644 --- a/Source/MainComponent.cpp +++ b/Source/MainComponent.cpp @@ -20,6 +20,7 @@ MainComponent::MainComponent(OscirenderAudioProcessor& p, OscirenderAudioProcess audioProcessor.addFile(file); } } + pluginEditor.addCodeEditor(audioProcessor.getCurrentFileIndex()); pluginEditor.updateCodeEditor(); updateFileLabel(); }); @@ -29,6 +30,11 @@ MainComponent::MainComponent(OscirenderAudioProcessor& p, OscirenderAudioProcess closeFileButton.setButtonText("Close File"); closeFileButton.onClick = [this] { + int index = audioProcessor.getCurrentFileIndex(); + if (index == -1) { + return; + } + pluginEditor.removeCodeEditor(audioProcessor.getCurrentFileIndex()); audioProcessor.removeFile(audioProcessor.getCurrentFileIndex()); pluginEditor.updateCodeEditor(); updateFileLabel(); diff --git a/Source/MainComponent.h b/Source/MainComponent.h index 1a483ce..6c47037 100644 --- a/Source/MainComponent.h +++ b/Source/MainComponent.h @@ -13,6 +13,7 @@ public: ~MainComponent() override; void resized() override; + void updateFileLabel(); private: OscirenderAudioProcessor& audioProcessor; OscirenderAudioProcessorEditor& pluginEditor; @@ -22,7 +23,5 @@ private: juce::TextButton closeFileButton; juce::Label fileLabel; - void updateFileLabel(); - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MainComponent) }; \ No newline at end of file diff --git a/Source/PluginEditor.cpp b/Source/PluginEditor.cpp index ccf1d98..2e7da2e 100644 --- a/Source/PluginEditor.cpp +++ b/Source/PluginEditor.cpp @@ -21,48 +21,27 @@ OscirenderAudioProcessorEditor::OscirenderAudioProcessorEditor(OscirenderAudioPr addAndMakeVisible(effects); addAndMakeVisible(main); - codeEditor = std::make_unique(codeDocument, &luaTokeniser); - addAndMakeVisible(*codeEditor); - - codeEditor->loadContent (R"LUA( - -- defines a factorial function - function fact (n) - if n == 0 then - return 1 - else - return n * fact(n-1) - end - end - - print("enter a number:") - a = io.read("*number") -- read a number - print(fact(a)) -)LUA"); - - // I need to disable accessibility otherwise it doesn't work! Appears to be a JUCE issue, very annoying! - codeEditor->setAccessible(false); - - // listen for changes to the code editor - codeDocument.addListener(this); - addAndMakeVisible(collapseButton); collapseButton.onClick = [this] { - if (codeEditor->isVisible()) { - codeEditor->setVisible(false); - juce::Path path; - path.addTriangle(0.0f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f); - collapseButton.setShape(path, false, true, true); - } else { - codeEditor->setVisible(true); - updateCodeEditor(); - juce::Path path; - path.addTriangle(0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.5f); - collapseButton.setShape(path, false, true, true); - } - resized(); + int index = audioProcessor.getCurrentFileIndex(); + if (index != -1) { + if (codeEditors[index]->isVisible()) { + codeEditors[index]->setVisible(false); + juce::Path path; + path.addTriangle(0.0f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f); + collapseButton.setShape(path, false, true, true); + } else { + codeEditors[index]->setVisible(true); + updateCodeEditor(); + juce::Path path; + path.addTriangle(0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.5f); + collapseButton.setShape(path, false, true, true); + } + resized(); + } }; juce::Path path; - path.addTriangle(0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.5f); + path.addTriangle(0.0f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f); collapseButton.setShape(path, false, true, true); resized(); } @@ -81,54 +60,101 @@ void OscirenderAudioProcessorEditor::paint (juce::Graphics& g) void OscirenderAudioProcessorEditor::resized() { auto area = getLocalBounds(); auto sections = 2; - if (codeEditor != nullptr) { - if (codeEditor->isVisible()) { + int index = audioProcessor.getCurrentFileIndex(); + if (index != -1) { + if (codeEditors[index]->isVisible()) { sections++; - codeEditor->setBounds(area.removeFromRight(getWidth() / sections)); + codeEditors[index]->setBounds(area.removeFromRight(getWidth() / sections)); } else { - codeEditor->setBounds(0, 0, 0, 0); + codeEditors[index]->setBounds(0, 0, 0, 0); } collapseButton.setBounds(area.removeFromRight(20)); - } + } else { + collapseButton.setBounds(0, 0, 0, 0); + } effects.setBounds(area.removeFromRight(getWidth() / sections)); main.setBounds(area.removeFromTop(getHeight() / 2)); } +void OscirenderAudioProcessorEditor::addCodeEditor(int index) { + std::shared_ptr codeDocument = std::make_shared(); + codeDocuments.insert(codeDocuments.begin() + index, codeDocument); + juce::String extension = audioProcessor.getFile(index).getFileExtension(); + juce::CodeTokeniser* tokeniser = nullptr; + if (extension == ".lua") { + tokeniser = &luaTokeniser; + } else if (extension == ".svg") { + tokeniser = &xmlTokeniser; + } + std::shared_ptr editor = std::make_shared(*codeDocument, tokeniser); + // I need to disable accessibility otherwise it doesn't work! Appears to be a JUCE issue, very annoying! + editor->setAccessible(false); + // listen for changes to the code editor + codeDocument->addListener(this); + codeEditors.insert(codeEditors.begin() + index, editor); + addChildComponent(*editor); +} + +void OscirenderAudioProcessorEditor::removeCodeEditor(int index) { + codeEditors.erase(codeEditors.begin() + index); + codeDocuments.erase(codeDocuments.begin() + index); +} + void OscirenderAudioProcessorEditor::updateCodeEditor() { - if (codeEditor->isVisible() && audioProcessor.getCurrentFileIndex() != -1) { - codeEditor->loadContent(juce::MemoryInputStream(*audioProcessor.getFileBlock(audioProcessor.getCurrentFileIndex()), false).readEntireStreamAsString()); + // check if any code editors are visible + bool visible = false; + for (int i = 0; i < codeEditors.size(); i++) { + if (codeEditors[i]->isVisible()) { + visible = true; + break; + } + } + int index = audioProcessor.getCurrentFileIndex(); + if (index != -1 && visible) { + for (int i = 0; i < codeEditors.size(); i++) { + codeEditors[i]->setVisible(false); + } + codeEditors[index]->setVisible(true); + codeEditors[index]->loadContent(juce::MemoryInputStream(*audioProcessor.getFileBlock(index), false).readEntireStreamAsString()); } + resized(); } void OscirenderAudioProcessorEditor::codeDocumentTextInserted(const juce::String& newText, int insertIndex) { - juce::String file = codeDocument.getAllContent(); - audioProcessor.updateFileBlock(audioProcessor.getCurrentFileIndex(), std::make_shared(file.toRawUTF8(), file.getNumBytesAsUTF8() + 1)); + int index = audioProcessor.getCurrentFileIndex(); + juce::String file = codeDocuments[index]->getAllContent(); + audioProcessor.updateFileBlock(index, std::make_shared(file.toRawUTF8(), file.getNumBytesAsUTF8() + 1)); } void OscirenderAudioProcessorEditor::codeDocumentTextDeleted(int startIndex, int endIndex) { - juce::String file = codeDocument.getAllContent(); - audioProcessor.updateFileBlock(audioProcessor.getCurrentFileIndex(), std::make_shared(file.toRawUTF8(), file.getNumBytesAsUTF8() + 1)); + int index = audioProcessor.getCurrentFileIndex(); + juce::String file = codeDocuments[index]->getAllContent(); + audioProcessor.updateFileBlock(index, std::make_shared(file.toRawUTF8(), file.getNumBytesAsUTF8() + 1)); } bool OscirenderAudioProcessorEditor::keyPressed(const juce::KeyPress& key) { int numFiles = audioProcessor.numFiles(); int currentFile = audioProcessor.getCurrentFileIndex(); + bool updated = false; if (key.getTextCharacter() == 'j') { currentFile++; if (currentFile == numFiles) { currentFile = 0; } - audioProcessor.changeCurrentFile(currentFile); - updateCodeEditor(); - return true; + updated = true; } else if (key.getTextCharacter() == 'k') { currentFile--; if (currentFile < 0) { currentFile = numFiles - 1; } + updated = true; + } + + if (updated) { audioProcessor.changeCurrentFile(currentFile); updateCodeEditor(); - return true; + main.updateFileLabel(); } - return false; + + return updated; } diff --git a/Source/PluginEditor.h b/Source/PluginEditor.h index 8035de7..d559687 100644 --- a/Source/PluginEditor.h +++ b/Source/PluginEditor.h @@ -26,16 +26,19 @@ public: //============================================================================== void paint (juce::Graphics&) override; void resized() override; - + + void addCodeEditor(int index); + void removeCodeEditor(int index); void updateCodeEditor(); private: OscirenderAudioProcessor& audioProcessor; MainComponent main; EffectsComponent effects; - juce::CodeDocument codeDocument; + std::vector> codeDocuments; + std::vector> codeEditors; juce::LuaTokeniser luaTokeniser; - std::unique_ptr codeEditor; + juce::XmlTokeniser xmlTokeniser; juce::ShapeButton collapseButton; void codeDocumentTextInserted(const juce::String& newText, int insertIndex) override; diff --git a/Source/PluginProcessor.cpp b/Source/PluginProcessor.cpp index a15aab7..c4352df 100644 --- a/Source/PluginProcessor.cpp +++ b/Source/PluginProcessor.cpp @@ -241,6 +241,10 @@ void OscirenderAudioProcessor::openFile(int index) { } void OscirenderAudioProcessor::changeCurrentFile(int index) { + if (index == -1) { + currentFile = -1; + producer->setSource(std::make_shared(), -1); + } if (index < 0 || index >= fileBlocks.size()) { return; } @@ -257,6 +261,10 @@ juce::File OscirenderAudioProcessor::getCurrentFile() { return files[currentFile]; } +juce::File OscirenderAudioProcessor::getFile(int index) { + return files[index]; +} + std::shared_ptr OscirenderAudioProcessor::getFileBlock(int index) { return fileBlocks[index]; } diff --git a/Source/PluginProcessor.h b/Source/PluginProcessor.h index d98e0b6..5edbc69 100644 --- a/Source/PluginProcessor.h +++ b/Source/PluginProcessor.h @@ -95,6 +95,7 @@ public: void changeCurrentFile(int index); int getCurrentFileIndex(); juce::File getCurrentFile(); + juce::File getFile(int index); std::shared_ptr getFileBlock(int index); private: double theta = 0.0; diff --git a/Source/parser/FrameProducer.h b/Source/parser/FrameProducer.h index 65b3991..4ae980f 100644 --- a/Source/parser/FrameProducer.h +++ b/Source/parser/FrameProducer.h @@ -14,5 +14,5 @@ public: private: FrameConsumer& frameConsumer; std::shared_ptr frameSource; - int sourceFileIndex = 0; + int sourceFileIndex = -1; }; \ No newline at end of file