Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

plugin: editor improvements #75

Merged
merged 5 commits into from
Dec 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions cmake.plugin.txt
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ function(add_new_target target_name is_synth)
"plugin/components/searchable_popup.h"
"plugin/components/modal_textinputbox.h"
"plugin/components/divider.h"
"plugin/components/tokenizer.h"
"plugin/components/tokenizer_functions.h"
"plugin/components/tokenizer.cpp"
"plugin/utility/audio_processor_suspender.h"
"plugin/utility/functional_timer.h"
"plugin/utility/async_updater.cpp"
Expand Down
37 changes: 21 additions & 16 deletions plugin/components/ide_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#include "lookandfeel.h"
#include "ide_view.h"
#include "utility/functional_timer.h"
#include <juce_gui_extra/juce_gui_extra.h>
#include "tokenizer.h"
#include <algorithm>

struct YsfxIDEView::Impl {
Expand All @@ -27,7 +27,7 @@ struct YsfxIDEView::Impl {
juce::Time m_changeTime;
bool m_reloadDialogGuard = false;
std::unique_ptr<juce::CodeDocument> m_document;
std::unique_ptr<juce::CodeTokeniser> m_tokenizer;
std::unique_ptr<JSFXTokenizer> m_tokenizer;
std::unique_ptr<juce::CodeEditorComponent> m_editor;
std::unique_ptr<juce::TextButton> m_btnSave;
std::unique_ptr<juce::TextButton> m_btnUpdate;
Expand All @@ -49,6 +49,8 @@ struct YsfxIDEView::Impl {
juce::Array<VariableUI> m_vars;
std::unique_ptr<juce::Timer> m_varsUpdateTimer;

juce::File m_file{};

bool m_forceUpdate{false};

//==========================================================================
Expand All @@ -71,8 +73,7 @@ YsfxIDEView::YsfxIDEView()
m_impl->m_self = this;

m_impl->m_document.reset(new juce::CodeDocument);

//TODO code tokenizer
m_impl->m_tokenizer.reset(new JSFXTokenizer());

m_impl->createUI();
m_impl->connectUI();
Expand All @@ -86,6 +87,12 @@ YsfxIDEView::~YsfxIDEView()
{
}

void YsfxIDEView::setColourScheme(std::map<std::string, std::array<uint8_t, 3>> colormap)
{
m_impl->m_tokenizer->setColours(colormap);
m_impl->m_editor->setColourScheme(m_impl->m_tokenizer->getDefaultColourScheme());
}

void YsfxIDEView::setEffect(ysfx_t *fx, juce::Time timeStamp)
{
if (m_impl->m_fx.get() == fx)
Expand Down Expand Up @@ -146,10 +153,11 @@ void YsfxIDEView::Impl::setupNewFx()
}
else {
juce::File file{juce::CharPointer_UTF8{ysfx_get_file_path(fx)}};
if (file != juce::File{}) m_file = file;

{
juce::MemoryBlock memBlock;
if (file.loadFileAsData(memBlock)) {
if (m_file.loadFileAsData(memBlock)) {
juce::String newContent = memBlock.toString();
memBlock = {};
if (newContent != m_document->getAllContent()) {
Expand Down Expand Up @@ -207,9 +215,8 @@ void YsfxIDEView::Impl::saveAs()
if (m_fileChooserActive) return;

juce::File initialPath;
juce::File prevFilePath{juce::CharPointer_UTF8{ysfx_get_file_path(m_fx.get())}};
if (prevFilePath != juce::File{}) {
initialPath = prevFilePath.getParentDirectory();
if (m_file != juce::File{}) {
initialPath = m_file.getParentDirectory();
}

m_fileChooser.reset(new juce::FileChooser(TRANS("Choose filename to save JSFX to"), initialPath));
Expand Down Expand Up @@ -273,10 +280,9 @@ void YsfxIDEView::Impl::saveCurrentFile()
if (!fx)
return;

juce::File file = juce::File{juce::CharPointer_UTF8{ysfx_get_file_path(fx)}};
if (file.existsAsFile()) {
if (m_file.existsAsFile()) {
m_btnSave->setEnabled(false);
saveFile(file);
saveFile(m_file);
} else {
saveAs();
}
Expand All @@ -288,11 +294,10 @@ void YsfxIDEView::Impl::checkFileForModifications()
if (!fx)
return;

juce::File file{juce::CharPointer_UTF8{ysfx_get_file_path(fx)}};
if (file == juce::File{})
if (m_file == juce::File{})
return;

juce::Time newMtime = file.getLastModificationTime();
juce::Time newMtime = m_file.getLastModificationTime();
if (newMtime == juce::Time{})
return;

Expand All @@ -302,11 +307,11 @@ void YsfxIDEView::Impl::checkFileForModifications()
if (!m_reloadDialogGuard) {
m_reloadDialogGuard = true;

auto callback = [this, file](int result) {
auto callback = [this](int result) {
m_reloadDialogGuard = false;
if (result != 0) {
if (m_self->onReloadRequested)
m_self->onReloadRequested(file);
m_self->onReloadRequested(m_file);
}
};

Expand Down
1 change: 1 addition & 0 deletions plugin/components/ide_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class YsfxIDEView : public juce::Component {
public:
YsfxIDEView();
~YsfxIDEView() override;
void setColourScheme(std::map<std::string, std::array<uint8_t, 3>> colormap);
void setEffect(ysfx_t *fx, juce::Time timeStamp);
void setStatusText(const juce::String &text);
void focusOnCodeEditor();
Expand Down
12 changes: 10 additions & 2 deletions plugin/components/modal_textinputbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class ExclusionFilter : public juce::TextEditor::InputFilter
};


static juce::AlertWindow* show_async_text_input(juce::String title, juce::String message, std::function<void(juce::String, bool)> callback, std::optional<std::function<juce::String(juce::String)>> validator=std::nullopt)
static juce::AlertWindow* show_async_text_input(juce::String title, juce::String message, std::function<void(juce::String, bool)> callback, std::optional<std::function<juce::String(juce::String)>> validator=std::nullopt, juce::Component* parent=nullptr)
{
auto* window = new juce::AlertWindow(title, message, juce::AlertWindow::NoIcon);
window->addTextEditor("textField", "", "");
Expand Down Expand Up @@ -61,11 +61,15 @@ static juce::AlertWindow* show_async_text_input(juce::String title, juce::String
textEditor->setWantsKeyboardFocus(true);
textEditor->grabKeyboardFocus();

if (parent) {
window->setCentrePosition(parent->getScreenPosition() + juce::Point<int>{parent->getScreenBounds().getWidth() / 2, parent->getScreenBounds().getHeight() / 2});
}

return window;
}


static juce::AlertWindow* show_overwrite_window(juce::String title, juce::String message, std::vector<juce::String> buttons, std::function<void(int result)> callback)
static juce::AlertWindow* show_option_window(juce::String title, juce::String message, std::vector<juce::String> buttons, std::function<void(int result)> callback, juce::Component* parent=nullptr)
{
auto* window = new juce::AlertWindow(title, message, juce::AlertWindow::NoIcon);
window->setMessage(message);
Expand All @@ -89,5 +93,9 @@ static juce::AlertWindow* show_overwrite_window(juce::String title, juce::String
window->grabKeyboardFocus();
window->setEscapeKeyCancels(true);

if (parent) {
window->setCentrePosition(parent->getScreenPosition() + juce::Point<int>{parent->getScreenBounds().getWidth() / 2, parent->getScreenBounds().getHeight() / 2});
}

return window;
}
46 changes: 20 additions & 26 deletions plugin/components/rpl_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,7 @@ class LoadedBank : public juce::Component, public juce::DragAndDropContainer {
[this](const juce::FileChooser &chooser) {
juce::File result = chooser.getResult();
if (result != juce::File()) {
if (this) {
this->setFile(result);
}
this->setFile(result);
}
}
);
Expand Down Expand Up @@ -254,31 +252,27 @@ class LoadedBank : public juce::Component, public juce::DragAndDropContainer {

if (names.empty()) return;

juce::AlertWindow::showAsync
(
juce::MessageBoxOptions()
.withTitle("Are you certain?")
.withMessage(
m_confirmDialog.reset(
show_option_window(
TRANS("Are you certain?"),
TRANS("Are you certain you want to delete ") +
((names.size() > 1) ? TRANS("several presets") : names[0])
+ "\n" + TRANS("This operation cannot be undone!")
)
.withButton("Yes")
.withButton("No")
.withParentComponent(this)
.withIconType(juce::MessageBoxIconType::NoIcon),
[this, names](int result){
if (result == 1) {
for (auto name : names)
{
m_bank.reset(ysfx_delete_preset_from_bank(m_bank.get(), name.c_str()));
}
+ "?\n" + TRANS("This operation cannot be undone!"),
std::vector<juce::String>{"Yes", "No"},
[this, names](int result){
if (result == 1) {
for (auto name : names)
{
m_bank.reset(ysfx_delete_preset_from_bank(m_bank.get(), name.c_str()));
}

this->m_listBox->deselectAllRows();
save_bank(m_file.getFullPathName().toStdString().c_str(), m_bank.get());
if (m_bankUpdatedCallback) m_bankUpdatedCallback();
}
}
this->m_listBox->deselectAllRows();
save_bank(m_file.getFullPathName().toStdString().c_str(), m_bank.get());
if (m_bankUpdatedCallback) m_bankUpdatedCallback();
}
},
this
)
);
}

Expand Down Expand Up @@ -413,7 +407,7 @@ class LoadedBank : public juce::Component, public juce::DragAndDropContainer {
if (ysfx_preset_exists(m_bank.get(), src_bank->presets[idx].name) && !force_accept) {
// Ask for overwrite
m_confirmDialog.reset(
show_overwrite_window(
show_option_window(
TRANS("Are you certain?"),
TRANS("Are you certain you want to overwrite the preset named ") + juce::String(src_bank->presets[idx].name) + "?",
std::vector<juce::String>{"Yes", "No", "Yes to all", "Cancel"},
Expand Down
29 changes: 29 additions & 0 deletions plugin/components/tokenizer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include "tokenizer.h"
#include "tokenizer_functions.h"


JSFXTokenizer::JSFXTokenizer() {

}

void JSFXTokenizer::setColours(std::map<std::string, std::array<uint8_t, 3>> colormap)
{
std::vector<std::string> ideColors{
"error", "comment", "builtin_variable", "builtin_function", "builtin_core_function",
"builtin_section", "operator", "identifier", "integer", "float", "string", "bracket",
"punctuation", "preprocessor_text", "string_hash"
};

for (auto const& key : ideColors)
m_colourScheme.set(key, juce::Colour(colormap[key][0], colormap[key][1], colormap[key][2]));
}

juce::CodeEditorComponent::ColourScheme JSFXTokenizer::getDefaultColourScheme()
{
return m_colourScheme;
}

int JSFXTokenizer::readNextToken (juce::CodeDocument::Iterator& source)
{
return JSFXTokenizerFunctions::readNextJSFXToken(source);
}
36 changes: 36 additions & 0 deletions plugin/components/tokenizer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include <vector>
#include <array>
#include <string>
#include <juce_gui_extra/juce_gui_extra.h>

class JSFXTokenizer : public juce::CPlusPlusCodeTokeniser
{
public:
JSFXTokenizer();
void setColours(std::map<std::string, std::array<uint8_t, 3>> colormap);
juce::CodeEditorComponent::ColourScheme getDefaultColourScheme() override;

/** The token values returned by this tokeniser. */
enum TokenType
{
tokenType_error = 0,
tokenType_comment,
tokenType_builtin_variable,
tokenType_builtin_function,
tokenType_builtin_core_function,
tokenType_builtin_section,
tokenType_operator,
tokenType_identifier,
tokenType_integer,
tokenType_float,
tokenType_string,
tokenType_bracket,
tokenType_punctuation,
tokenType_preprocessor,
tokenType_string_hash,
};

private:
int readNextToken(juce::CodeDocument::Iterator& source);
juce::CodeEditorComponent::ColourScheme m_colourScheme;
};
Loading
Loading