Browse Source

Changed onSelect/onDeselect to onFocus/onDefocus, added key commands for Open/Save/Save As, open in last used directory

tags/v0.3.2
Andrew Belt 7 years ago
parent
commit
970e227c20
15 changed files with 149 additions and 52 deletions
  1. +5
    -0
      include/app.hpp
  2. +1
    -0
      include/gui.hpp
  3. +3
    -0
      include/util.hpp
  4. +8
    -8
      include/widgets.hpp
  5. +8
    -6
      src/app/ModuleWidget.cpp
  6. +18
    -2
      src/app/RackScene.cpp
  7. +31
    -0
      src/app/RackWidget.cpp
  8. +13
    -16
      src/app/Toolbar.cpp
  9. +10
    -0
      src/core/MidiInterface.cpp
  10. +1
    -0
      src/core/core.hpp
  11. +26
    -11
      src/gui.cpp
  12. +16
    -0
      src/util.cpp
  13. +1
    -1
      src/widgets.cpp
  14. +4
    -4
      src/widgets/TextField.cpp
  15. +4
    -4
      src/widgets/Widget.cpp

+ 5
- 0
include/app.hpp View File

@@ -90,10 +90,15 @@ struct RackWidget : OpaqueWidget {
// Only put WireWidgets in here
Widget *wireContainer;
WireWidget *activeWire = NULL;
std::string lastPath;

RackWidget();
~RackWidget();

void clear();
void openDialog();
void saveDialog();
void saveAsDialog();
void savePatch(std::string filename);
void loadPatch(std::string filename);
json_t *toJson();


+ 1
- 0
include/gui.hpp View File

@@ -29,5 +29,6 @@ void guiClose();
void guiCursorLock();
void guiCursorUnlock();
bool guiIsModPressed();
bool guiIsShiftPressed();

} // namespace rack

+ 3
- 0
include/util.hpp View File

@@ -52,6 +52,9 @@ std::string stringf(const char *format, ...);
/** Truncates and adds "..." to a string, not exceeding `len` characters */
std::string ellipsize(std::string s, size_t len);

std::string extractDirectory(std::string path);
std::string extractFilename(std::string path);

/** Opens a URL, also happens to work with PDFs and folders.
Shell injection is possible, so make sure the URL is trusted or hard coded.
May block, so open in a new thread.


+ 8
- 8
include/widgets.hpp View File

@@ -100,10 +100,10 @@ struct Widget {
virtual void onMouseEnter() {}
/** Called when another widget begins responding to `onMouseMove` events */
virtual void onMouseLeave() {}
virtual void onSelect() {}
virtual void onDeselect() {}
virtual bool onText(int codepoint) {return false;}
virtual bool onKey(int key) {return false;}
virtual void onFocus() {}
virtual void onDefocus() {}
virtual bool onFocusText(int codepoint) {return false;}
virtual bool onFocusKey(int key) {return false;}
virtual Widget *onScroll(Vec pos, Vec scrollRel);

/** Called when a widget responds to `onMouseDown` for a left button press */
@@ -370,9 +370,9 @@ struct TextField : OpaqueWidget {
}
void draw(NVGcontext *vg);
Widget *onMouseDown(Vec pos, int button);
bool onText(int codepoint);
bool onKey(int scancode);
void onSelect();
bool onFocusText(int codepoint);
bool onFocusKey(int scancode);
void onFocus();
void insertText(std::string newText);
};

@@ -408,7 +408,7 @@ extern Vec gMousePos;
extern Widget *gHoveredWidget;
extern Widget *gDraggedWidget;
extern Widget *gDragHoveredWidget;
extern Widget *gSelectedWidget;
extern Widget *gFocusedWidget;
extern int gGuiFrame;

extern Scene *gScene;


+ 8
- 6
src/app/ModuleWidget.cpp View File

@@ -155,20 +155,22 @@ Widget *ModuleWidget::onHoverKey(Vec pos, int key) {
switch (key) {
case GLFW_KEY_DELETE:
case GLFW_KEY_BACKSPACE:
gRackWidget->deleteModule(this);
this->finalizeEvents();
delete this;
if (!guiIsModPressed() && !guiIsShiftPressed()) {
gRackWidget->deleteModule(this);
this->finalizeEvents();
delete this;
}
break;
case GLFW_KEY_I:
if (guiIsModPressed())
if (guiIsModPressed() && !guiIsShiftPressed())
initialize();
break;
case GLFW_KEY_R:
if (guiIsModPressed())
if (guiIsModPressed() && !guiIsShiftPressed())
randomize();
break;
case GLFW_KEY_D:
if (guiIsModPressed())
if (guiIsModPressed() && !guiIsShiftPressed())
gRackWidget->cloneModule(this);
break;
}


+ 18
- 2
src/app/RackScene.cpp View File

@@ -70,17 +70,33 @@ void RackScene::draw(NVGcontext *vg) {
Widget *RackScene::onHoverKey(Vec pos, int key) {
switch (key) {
case GLFW_KEY_N:
if (guiIsModPressed()) {
if (guiIsModPressed() && !guiIsShiftPressed()) {
gRackWidget->clear();
return this;
}
break;
case GLFW_KEY_Q:
if (guiIsModPressed()) {
if (guiIsModPressed() && !guiIsShiftPressed()) {
guiClose();
return this;
}
break;
case GLFW_KEY_O:
if (guiIsModPressed() && !guiIsShiftPressed()) {
gRackWidget->openDialog();
return this;
}
break;
case GLFW_KEY_S:
if (guiIsModPressed() && !guiIsShiftPressed()) {
gRackWidget->saveDialog();
return this;
}
if (guiIsModPressed() && guiIsShiftPressed()) {
gRackWidget->saveAsDialog();
return this;
}
break;
}

return Widget::onHoverKey(pos, key);


+ 31
- 0
src/app/RackWidget.cpp View File

@@ -4,6 +4,7 @@
#include "engine.hpp"
#include "plugin.hpp"
#include "gui.hpp"
#include "../ext/osdialog/osdialog.h"


namespace rack {
@@ -46,6 +47,36 @@ void RackWidget::clear() {
moduleContainer->clearChildren();
}

void RackWidget::openDialog() {
std::string dir = lastPath.empty() ? "." : extractDirectory(lastPath);
char *path = osdialog_file(OSDIALOG_OPEN, dir.c_str(), NULL, NULL);
if (path) {
loadPatch(path);
lastPath = path;
free(path);
}
}

void RackWidget::saveDialog() {
if (!lastPath.empty()) {
savePatch(lastPath);
}
else {
saveAsDialog();
}
}

void RackWidget::saveAsDialog() {
std::string dir = lastPath.empty() ? "." : extractDirectory(lastPath);
char *path = osdialog_file(OSDIALOG_SAVE, dir.c_str(), "Untitled.vcv", NULL);
if (path) {
savePatch(path);
lastPath = path;
free(path);
}
}


void RackWidget::savePatch(std::string filename) {
printf("Saving patch %s\n", filename.c_str());
FILE *file = fopen(filename.c_str(), "w");


+ 13
- 16
src/app/Toolbar.cpp View File

@@ -1,7 +1,6 @@
#include "app.hpp"
#include "gui.hpp"
#include "engine.hpp"
#include "../ext/osdialog/osdialog.h"


namespace rack {
@@ -13,23 +12,21 @@ struct NewItem : MenuItem {
}
};

struct OpenItem : MenuItem {
void onAction() {
gRackWidget->openDialog();
}
};

struct SaveItem : MenuItem {
void onAction() {
char *path = osdialog_file(OSDIALOG_SAVE, "./patches", "Untitled.vcv", NULL);
if (path) {
gRackWidget->savePatch(path);
free(path);
}
gRackWidget->saveDialog();
}
};

struct OpenItem : MenuItem {
struct SaveAsItem : MenuItem {
void onAction() {
char *path = osdialog_file(OSDIALOG_OPEN, "./patches", NULL, NULL);
if (path) {
gRackWidget->loadPatch(path);
free(path);
}
gRackWidget->saveAsDialog();
}
};

@@ -48,11 +45,11 @@ struct FileChoice : ChoiceButton {
openItem->text = "Open";
menu->pushChild(openItem);

// MenuItem *saveItem = new SaveItem();
// saveItem->text = "Save";
// menu->pushChild(saveItem);
MenuItem *saveItem = new SaveItem();
saveItem->text = "Save";
menu->pushChild(saveItem);

MenuItem *saveAsItem = new SaveItem();
MenuItem *saveAsItem = new SaveAsItem();
saveAsItem->text = "Save As";
menu->pushChild(saveAsItem);
}


+ 10
- 0
src/core/MidiInterface.cpp View File

@@ -3,6 +3,7 @@
#include <algorithm>
#include <portmidi.h>
#include "core.hpp"
#include "gui.hpp"


using namespace rack;
@@ -408,3 +409,12 @@ MidiInterfaceWidget::MidiInterfaceWidget() {
yPos += 37 + margin;
}
}

void MidiInterfaceWidget::step() {
// Assume QWERTY
#define MIDI_KEY(key, midi) if (glfwGetKey(gWindow, key)) printf("%d\n", midi);

// MIDI_KEY(GLFW_KEY_Z, 48);

ModuleWidget::step();
}

+ 1
- 0
src/core/core.hpp View File

@@ -13,4 +13,5 @@ struct AudioInterfaceWidget : ModuleWidget {

struct MidiInterfaceWidget : ModuleWidget {
MidiInterfaceWidget();
void step();
};

+ 26
- 11
src/gui.cpp View File

@@ -56,14 +56,14 @@ void mouseButtonCallback(GLFWwindow *window, int button, int action, int mods) {
}
gDraggedWidget = w;

if (w != gSelectedWidget) {
if (gSelectedWidget) {
w->onDeselect();
if (w != gFocusedWidget) {
if (gFocusedWidget) {
w->onDefocus();
}
if (w) {
w->onSelect();
w->onFocus();
}
gSelectedWidget = w;
gFocusedWidget = w;
}
}
}
@@ -155,15 +155,15 @@ void scrollCallback(GLFWwindow *window, double x, double y) {
}

void charCallback(GLFWwindow *window, unsigned int codepoint) {
if (gSelectedWidget) {
gSelectedWidget->onText(codepoint);
if (gFocusedWidget) {
gFocusedWidget->onFocusText(codepoint);
}
}

void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) {
if (action == GLFW_PRESS || action == GLFW_REPEAT) {
// onKey
if (gSelectedWidget && gSelectedWidget->onKey(key))
// onFocusKey
if (gFocusedWidget && gFocusedWidget->onFocusKey(key))
return;
// onHoverKey
gScene->onHoverKey(gMousePos, key);
@@ -218,8 +218,7 @@ void guiInit() {
// glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_MAXIMIZED, GLFW_TRUE);
glfwWindowHint(GLFW_DOUBLEBUFFER, GLFW_TRUE);
std::string title = gApplicationName + " " + gApplicationVersion;
gWindow = glfwCreateWindow(640, 480, title.c_str(), NULL, NULL);
gWindow = glfwCreateWindow(640, 480, "", NULL, NULL);
if (!gWindow) {
osdialog_message(OSDIALOG_ERROR, OSDIALOG_OK, "Cannot open window with OpenGL 2.0 renderer. Does your graphics card support OpenGL 2.0? If so, are the latest drivers installed?");
exit(1);
@@ -280,12 +279,24 @@ void guiRun() {
double lastTime = 0.0;
while(!glfwWindowShouldClose(gWindow)) {
gGuiFrame++;

// Poll events
glfwPollEvents();
{
double xpos, ypos;
glfwGetCursorPos(gWindow, &xpos, &ypos);
cursorPosCallback(gWindow, xpos, ypos);
}

// Set window title
std::string title = gApplicationName + " " + gApplicationVersion;
if (!gRackWidget->lastPath.empty()) {
title += " - ";
title += extractFilename(gRackWidget->lastPath);
}
glfwSetWindowTitle(gWindow, title.c_str());

// Step scene
gScene->step();

// Render
@@ -332,6 +343,10 @@ bool guiIsModPressed() {
#endif
}

bool guiIsShiftPressed() {
return glfwGetKey(gWindow, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS || glfwGetKey(gWindow, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS;
}


////////////////////
// resources


+ 16
- 0
src/util.cpp View File

@@ -1,7 +1,9 @@
#include "util.hpp"
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <random>
#include <libgen.h> // for dirname and basename

#if ARCH_WIN
#include <windows.h>
@@ -53,6 +55,20 @@ std::string ellipsize(std::string s, size_t len) {
return s.substr(0, len - 3) + "...";
}

std::string extractDirectory(std::string path) {
char *pathDup = strdup(path.c_str());
std::string directory = dirname(pathDup);
free(pathDup);
return directory;
}

std::string extractFilename(std::string path) {
char *pathDup = strdup(path.c_str());
std::string filename = basename(pathDup);
free(pathDup);
return filename;
}

void openBrowser(std::string url) {
#if ARCH_LIN
std::string command = "xdg-open " + url;


+ 1
- 1
src/widgets.cpp View File

@@ -6,7 +6,7 @@ Vec gMousePos;
Widget *gHoveredWidget = NULL;
Widget *gDraggedWidget = NULL;
Widget *gDragHoveredWidget = NULL;
Widget *gSelectedWidget = NULL;
Widget *gFocusedWidget = NULL;
int gGuiFrame;

Scene *gScene = NULL;


+ 4
- 4
src/widgets/TextField.cpp View File

@@ -10,7 +10,7 @@ namespace rack {

void TextField::draw(NVGcontext *vg) {
BNDwidgetState state;
if (this == gSelectedWidget)
if (this == gFocusedWidget)
state = BND_ACTIVE;
else if (this == gHoveredWidget)
state = BND_HOVER;
@@ -29,14 +29,14 @@ Widget *TextField::onMouseDown(Vec pos, int button) {
}


bool TextField::onText(int codepoint) {
bool TextField::onFocusText(int codepoint) {
char c = codepoint;
std::string newText(1, c);
insertText(newText);
return true;
}

bool TextField::onKey(int key) {
bool TextField::onFocusKey(int key) {
switch (key) {
case GLFW_KEY_BACKSPACE:
if (begin < end) {
@@ -103,7 +103,7 @@ bool TextField::onKey(int key) {
return true;
}

void TextField::onSelect() {
void TextField::onFocus() {
begin = 0;
end = text.size();
}


+ 4
- 4
src/widgets/Widget.cpp View File

@@ -12,7 +12,7 @@ Widget::~Widget() {
if (gHoveredWidget == this) gHoveredWidget = NULL;
if (gDraggedWidget == this) gDraggedWidget = NULL;
if (gDragHoveredWidget == this) gDragHoveredWidget = NULL;
if (gSelectedWidget == this) gSelectedWidget = NULL;
if (gFocusedWidget == this) gFocusedWidget = NULL;
clearChildren();
}

@@ -76,9 +76,9 @@ void Widget::finalizeEvents() {
if (gDragHoveredWidget == this) {
gDragHoveredWidget = NULL;
}
if (gSelectedWidget == this) {
gSelectedWidget->onDeselect();
gSelectedWidget = NULL;
if (gFocusedWidget == this) {
gFocusedWidget->onDefocus();
gFocusedWidget = NULL;
}
for (Widget *child : children) {
child->finalizeEvents();


Loading…
Cancel
Save