| @@ -1 +1 @@ | |||||
| Subproject commit fbbfe11a5bb1a9d02f9fa7a341caae7e7d532e7e | |||||
| Subproject commit 29709cbe4e1f5d97b7630fd1664e2eb1210bb82f | |||||
| @@ -34,42 +34,34 @@ using namespace rack::widget; | |||||
| struct AsyncDialog : OpaqueWidget | struct AsyncDialog : OpaqueWidget | ||||
| { | { | ||||
| static const constexpr float margin = 10; | |||||
| static const constexpr float buttonWidth = 100; | |||||
| SequentialLayout* layout; | SequentialLayout* layout; | ||||
| SequentialLayout* contentLayout; | SequentialLayout* contentLayout; | ||||
| SequentialLayout* buttonLayout; | SequentialLayout* buttonLayout; | ||||
| Label* label; | Label* label; | ||||
| AsyncDialog(const char* const message, const std::function<void()> action) | |||||
| AsyncDialog(const char* const message) | |||||
| { | { | ||||
| box.size = math::Vec(400, 120); | |||||
| const float margin = 10; | |||||
| const float buttonWidth = 100; | |||||
| layout = new SequentialLayout; | |||||
| layout->box.pos = math::Vec(0, 0); | |||||
| layout->box.size = box.size; | |||||
| layout->orientation = SequentialLayout::VERTICAL_ORIENTATION; | |||||
| layout->margin = math::Vec(margin, margin); | |||||
| layout->spacing = math::Vec(margin, margin); | |||||
| layout->wrap = false; | |||||
| addChild(layout); | |||||
| setup(message); | |||||
| contentLayout = new SequentialLayout; | |||||
| contentLayout->spacing = math::Vec(margin, margin); | |||||
| layout->addChild(contentLayout); | |||||
| buttonLayout = new SequentialLayout; | |||||
| buttonLayout->alignment = SequentialLayout::CENTER_ALIGNMENT; | |||||
| buttonLayout->box.size = box.size; | |||||
| buttonLayout->spacing = math::Vec(margin, margin); | |||||
| layout->addChild(buttonLayout); | |||||
| struct AsyncDismissButton : Button { | |||||
| AsyncDialog* dialog; | |||||
| void onAction(const ActionEvent& e) override { | |||||
| dialog->getParent()->requestDelete(); | |||||
| } | |||||
| }; | |||||
| AsyncDismissButton* const dismissButton = new AsyncDismissButton; | |||||
| dismissButton->box.size.x = buttonWidth; | |||||
| dismissButton->text = "Dismiss"; | |||||
| dismissButton->dialog = this; | |||||
| buttonLayout->addChild(dismissButton); | |||||
| } | |||||
| label = new Label; | |||||
| label->box.size.x = box.size.x - 2*margin; | |||||
| label->box.size.y = box.size.y - 2*margin - 40; | |||||
| label->fontSize = 16; | |||||
| label->text = message; | |||||
| contentLayout->addChild(label); | |||||
| AsyncDialog(const char* const message, const std::function<void()> action) | |||||
| { | |||||
| setup(message); | |||||
| struct AsyncCancelButton : Button { | struct AsyncCancelButton : Button { | ||||
| AsyncDialog* dialog; | AsyncDialog* dialog; | ||||
| @@ -99,6 +91,37 @@ struct AsyncDialog : OpaqueWidget | |||||
| buttonLayout->addChild(okButton); | buttonLayout->addChild(okButton); | ||||
| } | } | ||||
| void setup(const char* const message) | |||||
| { | |||||
| box.size = math::Vec(400, 120); | |||||
| layout = new SequentialLayout; | |||||
| layout->box.pos = math::Vec(0, 0); | |||||
| layout->box.size = box.size; | |||||
| layout->orientation = SequentialLayout::VERTICAL_ORIENTATION; | |||||
| layout->margin = math::Vec(margin, margin); | |||||
| layout->spacing = math::Vec(margin, margin); | |||||
| layout->wrap = false; | |||||
| addChild(layout); | |||||
| contentLayout = new SequentialLayout; | |||||
| contentLayout->spacing = math::Vec(margin, margin); | |||||
| layout->addChild(contentLayout); | |||||
| buttonLayout = new SequentialLayout; | |||||
| buttonLayout->alignment = SequentialLayout::CENTER_ALIGNMENT; | |||||
| buttonLayout->box.size = box.size; | |||||
| buttonLayout->spacing = math::Vec(margin, margin); | |||||
| layout->addChild(buttonLayout); | |||||
| label = new Label; | |||||
| label->box.size.x = box.size.x - 2*margin; | |||||
| label->box.size.y = box.size.y - 2*margin - 40; | |||||
| label->fontSize = 16; | |||||
| label->text = message; | |||||
| contentLayout->addChild(label); | |||||
| } | |||||
| void step() override | void step() override | ||||
| { | { | ||||
| OpaqueWidget::step(); | OpaqueWidget::step(); | ||||
| @@ -113,6 +136,17 @@ struct AsyncDialog : OpaqueWidget | |||||
| } | } | ||||
| }; | }; | ||||
| void create(const char* const message) | |||||
| { | |||||
| MenuOverlay* const overlay = new MenuOverlay; | |||||
| overlay->bgColor = nvgRGBAf(0, 0, 0, 0.33); | |||||
| AsyncDialog* const dialog = new AsyncDialog(message); | |||||
| overlay->addChild(dialog); | |||||
| APP->scene->addChild(overlay); | |||||
| } | |||||
| void create(const char* const message, const std::function<void()> action) | void create(const char* const message, const std::function<void()> action) | ||||
| { | { | ||||
| MenuOverlay* const overlay = new MenuOverlay; | MenuOverlay* const overlay = new MenuOverlay; | ||||
| @@ -121,7 +155,7 @@ void create(const char* const message, const std::function<void()> action) | |||||
| AsyncDialog* const dialog = new AsyncDialog(message, action); | AsyncDialog* const dialog = new AsyncDialog(message, action); | ||||
| overlay->addChild(dialog); | overlay->addChild(dialog); | ||||
| APP->scene->addChild(overlay); | |||||
| APP->scene->addChild(overlay); | |||||
| } | } | ||||
| } | } | ||||
| @@ -22,6 +22,7 @@ | |||||
| namespace asyncDialog | namespace asyncDialog | ||||
| { | { | ||||
| void create(const char* message); | |||||
| void create(const char* message, std::function<void()> action); | void create(const char* message, std::function<void()> action); | ||||
| } | } | ||||
| @@ -20,6 +20,8 @@ | |||||
| #include <helpers.hpp> | #include <helpers.hpp> | ||||
| #include <patch.hpp> | #include <patch.hpp> | ||||
| #include <settings.hpp> | #include <settings.hpp> | ||||
| #include <string.hpp> | |||||
| #include <system.hpp> | |||||
| #include <ui/Button.hpp> | #include <ui/Button.hpp> | ||||
| #include <ui/MenuItem.hpp> | #include <ui/MenuItem.hpp> | ||||
| #include <ui/MenuSeparator.hpp> | #include <ui/MenuSeparator.hpp> | ||||
| @@ -30,7 +32,7 @@ | |||||
| #endif | #endif | ||||
| #include <Application.hpp> | #include <Application.hpp> | ||||
| #include "DistrhoUI.hpp" | |||||
| #include "AsyncDialog.hpp" | |||||
| #include "PluginContext.hpp" | #include "PluginContext.hpp" | ||||
| #include "WindowParameters.hpp" | #include "WindowParameters.hpp" | ||||
| #include "ResizeHandle.hpp" | #include "ResizeHandle.hpp" | ||||
| @@ -42,7 +44,7 @@ GLFWAPI int glfwGetKeyScancode(int key) { return 0; } | |||||
| namespace rack { | namespace rack { | ||||
| namespace app { | namespace app { | ||||
| widget::Widget* createMenuBar(Window& window, bool isStandalone); | |||||
| widget::Widget* createMenuBar(CardinalBaseUI* const ui, bool isStandalone); | |||||
| } | } | ||||
| namespace window { | namespace window { | ||||
| void WindowSetPluginUI(Window* window, DISTRHO_NAMESPACE::UI* ui); | void WindowSetPluginUI(Window* window, DISTRHO_NAMESPACE::UI* ui); | ||||
| @@ -54,14 +56,9 @@ START_NAMESPACE_DISTRHO | |||||
| // ----------------------------------------------------------------------------------------------------------- | // ----------------------------------------------------------------------------------------------------------- | ||||
| CardinalPluginContext* getRackContextFromPlugin(void* ptr); | |||||
| // ----------------------------------------------------------------------------------------------------------- | |||||
| class CardinalUI : public UI, | |||||
| class CardinalUI : public CardinalBaseUI, | |||||
| public WindowParametersCallback | public WindowParametersCallback | ||||
| { | { | ||||
| CardinalPluginContext* const fContext; | |||||
| rack::math::Vec fLastMousePos; | rack::math::Vec fLastMousePos; | ||||
| ResizeHandle fResizeHandle; | ResizeHandle fResizeHandle; | ||||
| WindowParameters fWindowParameters; | WindowParameters fWindowParameters; | ||||
| @@ -70,14 +67,14 @@ class CardinalUI : public UI, | |||||
| CardinalPluginContext* const context; | CardinalPluginContext* const context; | ||||
| ScopedContext(CardinalUI* const ui) | ScopedContext(CardinalUI* const ui) | ||||
| : context(ui->fContext) | |||||
| : context(ui->context) | |||||
| { | { | ||||
| rack::contextSet(context); | rack::contextSet(context); | ||||
| WindowParametersRestore(context->window); | WindowParametersRestore(context->window); | ||||
| } | } | ||||
| ScopedContext(CardinalUI* const ui, const int mods) | ScopedContext(CardinalUI* const ui, const int mods) | ||||
| : context(ui->fContext) | |||||
| : context(ui->context) | |||||
| { | { | ||||
| rack::contextSet(context); | rack::contextSet(context); | ||||
| rack::window::WindowSetMods(context->window, mods); | rack::window::WindowSetMods(context->window, mods); | ||||
| @@ -94,14 +91,13 @@ class CardinalUI : public UI, | |||||
| public: | public: | ||||
| CardinalUI() | CardinalUI() | ||||
| : UI(1228, 666), | |||||
| fContext(getRackContextFromPlugin(getPluginInstancePointer())), | |||||
| : CardinalBaseUI(1228, 666), | |||||
| fResizeHandle(this) | fResizeHandle(this) | ||||
| { | { | ||||
| Window& window(getWindow()); | Window& window(getWindow()); | ||||
| window.setIgnoringKeyRepeat(true); | window.setIgnoringKeyRepeat(true); | ||||
| fContext->nativeWindowId = window.getNativeWindowHandle(); | |||||
| context->nativeWindowId = window.getNativeWindowHandle(); | |||||
| if (isResizable()) | if (isResizable()) | ||||
| fResizeHandle.hide(); | fResizeHandle.hide(); | ||||
| @@ -111,32 +107,32 @@ public: | |||||
| if (scaleFactor != 1) | if (scaleFactor != 1) | ||||
| setSize(1228 * scaleFactor, 666 * scaleFactor); | setSize(1228 * scaleFactor, 666 * scaleFactor); | ||||
| rack::contextSet(fContext); | |||||
| rack::contextSet(context); | |||||
| rack::window::WindowSetPluginUI(fContext->window, this); | |||||
| rack::window::WindowSetPluginUI(context->window, this); | |||||
| if (fContext->scene->menuBar != nullptr) | |||||
| fContext->scene->removeChild(fContext->scene->menuBar); | |||||
| if (context->scene->menuBar != nullptr) | |||||
| context->scene->removeChild(context->scene->menuBar); | |||||
| fContext->scene->menuBar = rack::app::createMenuBar(window, getApp().isStandalone()); | |||||
| fContext->scene->addChildBelow(fContext->scene->menuBar, fContext->scene->rackScroll); | |||||
| context->scene->menuBar = rack::app::createMenuBar(this, getApp().isStandalone()); | |||||
| context->scene->addChildBelow(context->scene->menuBar, context->scene->rackScroll); | |||||
| fContext->window->step(); | |||||
| context->window->step(); | |||||
| rack::contextSet(nullptr); | rack::contextSet(nullptr); | ||||
| WindowParametersSetCallback(fContext->window, this); | |||||
| WindowParametersSetCallback(context->window, this); | |||||
| } | } | ||||
| ~CardinalUI() override | ~CardinalUI() override | ||||
| { | { | ||||
| rack::contextSet(fContext); | |||||
| rack::contextSet(context); | |||||
| rack::widget::Widget* const menuBar = fContext->scene->menuBar; | |||||
| fContext->scene->menuBar = nullptr; | |||||
| fContext->scene->removeChild(menuBar); | |||||
| rack::widget::Widget* const menuBar = context->scene->menuBar; | |||||
| context->scene->menuBar = nullptr; | |||||
| context->scene->removeChild(menuBar); | |||||
| rack::window::WindowSetPluginUI(fContext->window, nullptr); | |||||
| rack::window::WindowSetPluginUI(context->window, nullptr); | |||||
| rack::contextSet(nullptr); | rack::contextSet(nullptr); | ||||
| } | } | ||||
| @@ -144,7 +140,7 @@ public: | |||||
| void onNanoDisplay() override | void onNanoDisplay() override | ||||
| { | { | ||||
| const ScopedContext sc(this); | const ScopedContext sc(this); | ||||
| fContext->window->step(); | |||||
| context->window->step(); | |||||
| } | } | ||||
| void uiIdle() override | void uiIdle() override | ||||
| @@ -268,7 +264,7 @@ protected: | |||||
| return; | return; | ||||
| } | } | ||||
| WindowParametersSetValues(fContext->window, fWindowParameters); | |||||
| WindowParametersSetValues(context->window, fWindowParameters); | |||||
| } | } | ||||
| void stateChanged(const char* key, const char* value) override | void stateChanged(const char* key, const char* value) override | ||||
| @@ -378,7 +374,7 @@ protected: | |||||
| */ | */ | ||||
| const ScopedContext sc(this, mods); | const ScopedContext sc(this, mods); | ||||
| return fContext->event->handleButton(fLastMousePos, button, action, mods); | |||||
| return context->event->handleButton(fLastMousePos, button, action, mods); | |||||
| } | } | ||||
| bool onMotion(const MotionEvent& ev) override | bool onMotion(const MotionEvent& ev) override | ||||
| @@ -389,7 +385,7 @@ protected: | |||||
| fLastMousePos = mousePos; | fLastMousePos = mousePos; | ||||
| const ScopedContext sc(this, glfwMods(ev.mod)); | const ScopedContext sc(this, glfwMods(ev.mod)); | ||||
| return fContext->event->handleHover(mousePos, mouseDelta); | |||||
| return context->event->handleHover(mousePos, mouseDelta); | |||||
| } | } | ||||
| bool onScroll(const ScrollEvent& ev) override | bool onScroll(const ScrollEvent& ev) override | ||||
| @@ -402,7 +398,7 @@ protected: | |||||
| #endif | #endif | ||||
| const ScopedContext sc(this, glfwMods(ev.mod)); | const ScopedContext sc(this, glfwMods(ev.mod)); | ||||
| return fContext->event->handleScroll(fLastMousePos, scrollDelta); | |||||
| return context->event->handleScroll(fLastMousePos, scrollDelta); | |||||
| } | } | ||||
| bool onCharacterInput(const CharacterInputEvent& ev) override | bool onCharacterInput(const CharacterInputEvent& ev) override | ||||
| @@ -411,7 +407,7 @@ protected: | |||||
| return false; | return false; | ||||
| const ScopedContext sc(this, glfwMods(ev.mod)); | const ScopedContext sc(this, glfwMods(ev.mod)); | ||||
| return fContext->event->handleText(fLastMousePos, ev.character); | |||||
| return context->event->handleText(fLastMousePos, ev.character); | |||||
| } | } | ||||
| bool onKeyboard(const KeyboardEvent& ev) override | bool onKeyboard(const KeyboardEvent& ev) override | ||||
| @@ -486,15 +482,15 @@ protected: | |||||
| } | } | ||||
| const ScopedContext sc(this, mods); | const ScopedContext sc(this, mods); | ||||
| return fContext->event->handleKey(fLastMousePos, key, ev.keycode, action, mods); | |||||
| return context->event->handleKey(fLastMousePos, key, ev.keycode, action, mods); | |||||
| } | } | ||||
| void onResize(const ResizeEvent& ev) override | void onResize(const ResizeEvent& ev) override | ||||
| { | { | ||||
| UI::onResize(ev); | UI::onResize(ev); | ||||
| if (fContext->window != nullptr) | |||||
| fContext->window->setSize(rack::math::Vec(ev.size.getWidth(), ev.size.getHeight())); | |||||
| if (context->window != nullptr) | |||||
| context->window->setSize(rack::math::Vec(ev.size.getWidth(), ev.size.getHeight())); | |||||
| const double scaleFactor = getScaleFactor(); | const double scaleFactor = getScaleFactor(); | ||||
| char sizeString[64]; | char sizeString[64]; | ||||
| @@ -509,7 +505,7 @@ protected: | |||||
| return; | return; | ||||
| const ScopedContext sc(this, 0); | const ScopedContext sc(this, 0); | ||||
| fContext->event->handleLeave(); | |||||
| context->event->handleLeave(); | |||||
| } | } | ||||
| void uiFileBrowserSelected(const char* const filename) override | void uiFileBrowserSelected(const char* const filename) override | ||||
| @@ -517,9 +513,38 @@ protected: | |||||
| if (filename == nullptr) | if (filename == nullptr) | ||||
| return; | return; | ||||
| rack::contextSet(fContext); | |||||
| WindowParametersRestore(fContext->window); | |||||
| fContext->patch->loadAction(filename); | |||||
| rack::contextSet(context); | |||||
| WindowParametersRestore(context->window); | |||||
| std::string sfilename = filename; | |||||
| if (saving) | |||||
| { | |||||
| if (rack::system::getExtension(sfilename) != ".vcv") | |||||
| sfilename += ".vcv"; | |||||
| try { | |||||
| context->patch->save(sfilename); | |||||
| } | |||||
| catch (rack::Exception& e) { | |||||
| std::string message = rack::string::f("Could not save patch: %s", e.what()); | |||||
| asyncDialog::create(message.c_str()); | |||||
| return; | |||||
| } | |||||
| } | |||||
| else | |||||
| { | |||||
| try { | |||||
| context->patch->load(sfilename); | |||||
| } catch (rack::Exception& e) { | |||||
| std::string message = rack::string::f("Could not load patch: %s", e.what()); | |||||
| asyncDialog::create(message.c_str()); | |||||
| return; | |||||
| } | |||||
| } | |||||
| context->patch->path = sfilename; | |||||
| context->history->setSaved(); | |||||
| } | } | ||||
| #if 0 | #if 0 | ||||
| @@ -28,6 +28,10 @@ | |||||
| #include "DistrhoPlugin.hpp" | #include "DistrhoPlugin.hpp" | ||||
| #include "extra/Mutex.hpp" | #include "extra/Mutex.hpp" | ||||
| #ifndef HEADLESS | |||||
| # include "DistrhoUI.hpp" | |||||
| #endif | |||||
| START_NAMESPACE_DISTRHO | START_NAMESPACE_DISTRHO | ||||
| // ----------------------------------------------------------------------------------------------------------- | // ----------------------------------------------------------------------------------------------------------- | ||||
| @@ -86,6 +90,8 @@ struct CardinalAudioDevice; | |||||
| struct CardinalMidiInputDevice; | struct CardinalMidiInputDevice; | ||||
| struct CardinalMidiOutputDevice; | struct CardinalMidiOutputDevice; | ||||
| CardinalPluginContext* getRackContextFromPlugin(void* ptr); | |||||
| class CardinalBasePlugin : public Plugin { | class CardinalBasePlugin : public Plugin { | ||||
| public: | public: | ||||
| CardinalPluginContext* const context; | CardinalPluginContext* const context; | ||||
| @@ -106,6 +112,18 @@ public: | |||||
| virtual bool clearMidiOutputDevice(CardinalMidiOutputDevice* dev) noexcept = 0; | virtual bool clearMidiOutputDevice(CardinalMidiOutputDevice* dev) noexcept = 0; | ||||
| }; | }; | ||||
| class CardinalBaseUI : public UI { | |||||
| public: | |||||
| CardinalPluginContext* const context; | |||||
| bool saving; | |||||
| CardinalBaseUI(const uint width, const uint height) | |||||
| : UI(width, height), | |||||
| context(getRackContextFromPlugin(getPluginInstancePointer())), | |||||
| saving(false) {} | |||||
| ~CardinalBaseUI() override {} | |||||
| }; | |||||
| // ----------------------------------------------------------------------------------------------------------- | // ----------------------------------------------------------------------------------------------------------- | ||||
| END_NAMESPACE_DISTRHO | END_NAMESPACE_DISTRHO | ||||
| @@ -108,8 +108,29 @@ static void promptClear(const char* const message, const std::function<void()> a | |||||
| asyncDialog::create(message, action); | asyncDialog::create(message, action); | ||||
| } | } | ||||
| static std::string homeDir() | |||||
| { | |||||
| #ifdef ARCH_WIN | |||||
| if (const char* const userprofile = getenv("USERPROFILE")) | |||||
| { | |||||
| return userprofile; | |||||
| } | |||||
| else if (const char* const homedrive = getenv("HOMEDRIVE")) | |||||
| { | |||||
| if (const char* const homepath = getenv("HOMEPATH")) | |||||
| return system::join(homedrive, homepath); | |||||
| } | |||||
| #else | |||||
| if (struct passwd* const pwd = getpwuid(getuid())) | |||||
| return pwd->pw_dir; | |||||
| else if (const char* const home = getenv("HOME")) | |||||
| return home; | |||||
| #endif | |||||
| return {}; | |||||
| } | |||||
| struct FileButton : MenuButton { | struct FileButton : MenuButton { | ||||
| Window& window; | |||||
| CardinalBaseUI* const ui; | |||||
| const bool isStandalone; | const bool isStandalone; | ||||
| #ifdef HAVE_LIBLO | #ifdef HAVE_LIBLO | ||||
| @@ -133,8 +154,8 @@ struct FileButton : MenuButton { | |||||
| } | } | ||||
| #endif | #endif | ||||
| FileButton(Window& win, const bool standalone) | |||||
| : MenuButton(), window(win), isStandalone(standalone) {} | |||||
| FileButton(CardinalBaseUI* const ui2, const bool standalone) | |||||
| : MenuButton(), ui(ui2), isStandalone(standalone) {} | |||||
| void onAction(const ActionEvent& e) override { | void onAction(const ActionEvent& e) override { | ||||
| ui::Menu* menu = createMenu(); | ui::Menu* menu = createMenu(); | ||||
| @@ -153,49 +174,30 @@ struct FileButton : MenuButton { | |||||
| promptClear("The current patch is unsaved. Clear it and open a new patch?", [this]() { | promptClear("The current patch is unsaved. Clear it and open a new patch?", [this]() { | ||||
| std::string dir; | std::string dir; | ||||
| if (! APP->patch->path.empty()) | if (! APP->patch->path.empty()) | ||||
| { | |||||
| dir = system::getDirectory(APP->patch->path); | dir = system::getDirectory(APP->patch->path); | ||||
| } | |||||
| else | else | ||||
| { | |||||
| // find home directory | |||||
| #ifdef ARCH_WIN | |||||
| if (const char* const userprofile = getenv("USERPROFILE")) | |||||
| { | |||||
| dir = userprofile; | |||||
| } | |||||
| else if (const char* const homedrive = getenv("HOMEDRIVE")) | |||||
| { | |||||
| if (const char* const homepath = getenv("HOMEPATH")) | |||||
| dir = system::join(homedrive, homepath); | |||||
| } | |||||
| #else | |||||
| if (struct passwd* const pwd = getpwuid(getuid())) | |||||
| dir = pwd->pw_dir; | |||||
| else if (const char* const home = getenv("HOME")) | |||||
| dir = home; | |||||
| #endif | |||||
| } | |||||
| dir = homeDir(); | |||||
| Window::FileBrowserOptions opts; | Window::FileBrowserOptions opts; | ||||
| opts.startDir = dir.c_str(); | opts.startDir = dir.c_str(); | ||||
| window.openFileBrowser(opts); | |||||
| opts.saving = ui->saving = false; | |||||
| ui->openFileBrowser(opts); | |||||
| }); | }); | ||||
| })); | })); | ||||
| /* | |||||
| menu->addChild(createMenuItem("Save", RACK_MOD_CTRL_NAME "+S", []() { | |||||
| APP->patch->saveDialog(); | |||||
| })); | |||||
| menu->addChild(createMenuItem("Save as", RACK_MOD_CTRL_NAME "+Shift+S", []() { | |||||
| APP->patch->saveAsDialog(); | |||||
| })); | |||||
| menu->addChild(createMenuItem("Save template", "", []() { | |||||
| APP->patch->saveTemplateDialog(); | |||||
| menu->addChild(createMenuItem("Export...", RACK_MOD_CTRL_NAME "+Shift+S", [this]() { | |||||
| // see APP->patch->saveAsDialog(); | |||||
| std::string dir; | |||||
| if (! APP->patch->path.empty()) | |||||
| dir = system::getDirectory(APP->patch->path); | |||||
| else | |||||
| dir = homeDir(); | |||||
| Window::FileBrowserOptions opts; | |||||
| opts.startDir = dir.c_str(); | |||||
| opts.saving = ui->saving = true; | |||||
| ui->openFileBrowser(opts); | |||||
| })); | })); | ||||
| */ | |||||
| #ifdef HAVE_LIBLO | #ifdef HAVE_LIBLO | ||||
| if (oscServer == nullptr || !oscConnected) { | if (oscServer == nullptr || !oscConnected) { | ||||
| @@ -680,7 +682,7 @@ struct MenuBar : widget::OpaqueWidget { | |||||
| // CardinalPluginContext* const context; | // CardinalPluginContext* const context; | ||||
| MeterLabel* meterLabel; | MeterLabel* meterLabel; | ||||
| MenuBar(Window& window, const bool isStandalone) | |||||
| MenuBar(CardinalBaseUI* const ui, const bool isStandalone) | |||||
| : widget::OpaqueWidget() | : widget::OpaqueWidget() | ||||
| // : context(ctx) | // : context(ctx) | ||||
| { | { | ||||
| @@ -692,7 +694,7 @@ struct MenuBar : widget::OpaqueWidget { | |||||
| layout->spacing = math::Vec(0, 0); | layout->spacing = math::Vec(0, 0); | ||||
| addChild(layout); | addChild(layout); | ||||
| FileButton* fileButton = new FileButton(window, isStandalone); | |||||
| FileButton* fileButton = new FileButton(ui, isStandalone); | |||||
| fileButton->text = "File"; | fileButton->text = "File"; | ||||
| layout->addChild(fileButton); | layout->addChild(fileButton); | ||||
| @@ -745,8 +747,8 @@ widget::Widget* createMenuBar() { | |||||
| return new widget::Widget; | return new widget::Widget; | ||||
| } | } | ||||
| widget::Widget* createMenuBar(Window& window, const bool isStandalone) { | |||||
| menuBar::MenuBar* menuBar = new menuBar::MenuBar(window, isStandalone); | |||||
| widget::Widget* createMenuBar(CardinalBaseUI* const ui, const bool isStandalone) { | |||||
| menuBar::MenuBar* menuBar = new menuBar::MenuBar(ui, isStandalone); | |||||
| return menuBar; | return menuBar; | ||||
| } | } | ||||