Implement file->export, show error message on failure
This commit is contained in:
parent
372f30b3e9
commit
fb9909e421
6 changed files with 190 additions and 110 deletions
2
dpf
2
dpf
|
|
@ -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)
|
||||||
|
{
|
||||||
|
setup(message);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
AsyncDialog(const char* const message, const std::function<void()> action)
|
AsyncDialog(const char* const message, const std::function<void()> action)
|
||||||
{
|
{
|
||||||
box.size = math::Vec(400, 120);
|
setup(message);
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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 CardinalBaseUI,
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
class CardinalUI : public UI,
|
|
||||||
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),
|
: CardinalBaseUI(1228, 666),
|
||||||
fContext(getRackContextFromPlugin(getPluginInstancePointer())),
|
|
||||||
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)
|
if (context->scene->menuBar != nullptr)
|
||||||
fContext->scene->removeChild(fContext->scene->menuBar);
|
context->scene->removeChild(context->scene->menuBar);
|
||||||
|
|
||||||
fContext->scene->menuBar = rack::app::createMenuBar(window, getApp().isStandalone());
|
context->scene->menuBar = rack::app::createMenuBar(this, getApp().isStandalone());
|
||||||
fContext->scene->addChildBelow(fContext->scene->menuBar, fContext->scene->rackScroll);
|
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;
|
rack::widget::Widget* const menuBar = context->scene->menuBar;
|
||||||
fContext->scene->menuBar = nullptr;
|
context->scene->menuBar = nullptr;
|
||||||
fContext->scene->removeChild(menuBar);
|
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)
|
if (context->window != nullptr)
|
||||||
fContext->window->setSize(rack::math::Vec(ev.size.getWidth(), ev.size.getHeight()));
|
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);
|
rack::contextSet(context);
|
||||||
WindowParametersRestore(fContext->window);
|
WindowParametersRestore(context->window);
|
||||||
fContext->patch->loadAction(filename);
|
|
||||||
|
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)
|
FileButton(CardinalBaseUI* const ui2, const bool standalone)
|
||||||
: MenuButton(), window(win), isStandalone(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,50 +174,31 @@ 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
|
||||||
{
|
dir = homeDir();
|
||||||
// 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
|
|
||||||
}
|
|
||||||
|
|
||||||
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("Export...", RACK_MOD_CTRL_NAME "+Shift+S", [this]() {
|
||||||
menu->addChild(createMenuItem("Save", RACK_MOD_CTRL_NAME "+S", []() {
|
// see APP->patch->saveAsDialog();
|
||||||
APP->patch->saveDialog();
|
std::string dir;
|
||||||
}));
|
if (! APP->patch->path.empty())
|
||||||
|
dir = system::getDirectory(APP->patch->path);
|
||||||
|
else
|
||||||
|
dir = homeDir();
|
||||||
|
|
||||||
menu->addChild(createMenuItem("Save as", RACK_MOD_CTRL_NAME "+Shift+S", []() {
|
Window::FileBrowserOptions opts;
|
||||||
APP->patch->saveAsDialog();
|
opts.startDir = dir.c_str();
|
||||||
|
opts.saving = ui->saving = true;
|
||||||
|
ui->openFileBrowser(opts);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
menu->addChild(createMenuItem("Save template", "", []() {
|
|
||||||
APP->patch->saveTemplateDialog();
|
|
||||||
}));
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_LIBLO
|
#ifdef HAVE_LIBLO
|
||||||
if (oscServer == nullptr || !oscConnected) {
|
if (oscServer == nullptr || !oscConnected) {
|
||||||
menu->addChild(createMenuItem("Connect to MOD", "", [this]() {
|
menu->addChild(createMenuItem("Connect to MOD", "", [this]() {
|
||||||
|
|
@ -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) {
|
widget::Widget* createMenuBar(CardinalBaseUI* const ui, const bool isStandalone) {
|
||||||
menuBar::MenuBar* menuBar = new menuBar::MenuBar(window, isStandalone);
|
menuBar::MenuBar* menuBar = new menuBar::MenuBar(ui, isStandalone);
|
||||||
return menuBar;
|
return menuBar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue