Browse Source

Added copy/paste from text and password fields

tags/v0.3.1
Andrew Belt 7 years ago
parent
commit
45d90342f9
5 changed files with 77 additions and 56 deletions
  1. +15
    -4
      include/gui.hpp
  2. +1
    -0
      include/widgets.hpp
  3. +2
    -6
      src/app/Knob.cpp
  4. +34
    -41
      src/gui.cpp
  5. +25
    -5
      src/widgets/TextField.cpp

+ 15
- 4
include/gui.hpp View File

@@ -1,19 +1,30 @@
#pragma once #pragma once
#include "app.hpp" #include "app.hpp"
#include <GL/glew.h>
#include <GLFW/glfw3.h>




namespace rack { namespace rack {




extern GLFWwindow *gWindow;
extern NVGcontext *gVg;
extern std::shared_ptr<Font> gGuiFont;
extern float gPixelRatio;


void guiInit(); void guiInit();
void guiDestroy(); void guiDestroy();
void guiRun(); void guiRun();
bool guiIsKeyPressed(int key);
void guiCursorLock(); void guiCursorLock();
void guiCursorUnlock(); void guiCursorUnlock();


extern NVGcontext *gVg;
extern std::shared_ptr<Font> gGuiFont;
extern float gPixelRatio;
inline bool guiIsModPressed() {
#ifdef ARCH_MAC
return glfwGetKey(gWindow, GLFW_KEY_LEFT_SUPER) == GLFW_PRESS || glfwGetKey(gWindow, GLFW_KEY_RIGHT_SUPER) == GLFW_PRESS;
#else
return glfwGetKey(gWindow, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS || glfwGetKey(gWindow, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS;
#endif
}


} // namespace rack } // namespace rack

+ 1
- 0
include/widgets.hpp View File

@@ -367,6 +367,7 @@ struct TextField : OpaqueWidget {
void onText(int codepoint); void onText(int codepoint);
void onKey(int scancode); void onKey(int scancode);
void onSelect(); void onSelect();
void insertText(std::string newText);
}; };


struct PasswordField : TextField { struct PasswordField : TextField {


+ 2
- 6
src/app/Knob.cpp View File

@@ -15,12 +15,8 @@ void Knob::onDragStart() {
} }


void Knob::onDragMove(Vec mouseRel) { void Knob::onDragMove(Vec mouseRel) {
// Drag slower if Ctrl is held (Command on Mac)
#ifdef ARCH_MAC
if (guiIsKeyPressed(GLFW_KEY_LEFT_SUPER) || guiIsKeyPressed(GLFW_KEY_RIGHT_SUPER))
#else
if (guiIsKeyPressed(GLFW_KEY_LEFT_CONTROL) || guiIsKeyPressed(GLFW_KEY_RIGHT_CONTROL))
#endif
// Drag slower if Mod
if (guiIsModPressed())
mouseRel = mouseRel.mult(0.1); mouseRel = mouseRel.mult(0.1);
setValue(value - KNOB_SENSITIVITY * (maxValue - minValue) * mouseRel.y); setValue(value - KNOB_SENSITIVITY * (maxValue - minValue) * mouseRel.y);
} }


+ 34
- 41
src/gui.cpp View File

@@ -1,8 +1,5 @@
#include <map> #include <map>


#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include "gui.hpp" #include "gui.hpp"
#include "app.hpp" #include "app.hpp"


@@ -24,7 +21,7 @@


namespace rack { namespace rack {


static GLFWwindow *window = NULL;
GLFWwindow *gWindow = NULL;
std::shared_ptr<Font> gGuiFont; std::shared_ptr<Font> gGuiFont;
NVGcontext *gVg = NULL; NVGcontext *gVg = NULL;
float gPixelRatio = 0.0; float gPixelRatio = 0.0;
@@ -92,15 +89,15 @@ void cursorPosCallback(GLFWwindow* window, double xpos, double ypos) {
#ifdef ARCH_MAC #ifdef ARCH_MAC
// Workaround for Mac. We can't use GLFW_CURSOR_DISABLED because it's buggy, so implement it on our own. // Workaround for Mac. We can't use GLFW_CURSOR_DISABLED because it's buggy, so implement it on our own.
// This is not an ideal implementation. For example, if the user drags off the screen, the new mouse position will be clamped. // This is not an ideal implementation. For example, if the user drags off the screen, the new mouse position will be clamped.
int mouseMode = glfwGetInputMode(window, GLFW_CURSOR);
int mouseMode = glfwGetInputMode(gWindow, GLFW_CURSOR);
if (mouseMode == GLFW_CURSOR_HIDDEN) { if (mouseMode == GLFW_CURSOR_HIDDEN) {
// CGSetLocalEventsSuppressionInterval(0.0); // CGSetLocalEventsSuppressionInterval(0.0);
glfwSetCursorPos(window, gMousePos.x, gMousePos.y);
glfwSetCursorPos(gWindow, gMousePos.x, gMousePos.y);
CGAssociateMouseAndMouseCursorPosition(true); CGAssociateMouseAndMouseCursorPosition(true);
mousePos = gMousePos; mousePos = gMousePos;
} }
// Because sometimes the cursor turns into an arrow when its position is on the boundary of the window // Because sometimes the cursor turns into an arrow when its position is on the boundary of the window
glfwSetCursor(window, NULL);
glfwSetCursor(gWindow, NULL);
#endif #endif


gMousePos = mousePos; gMousePos = mousePos;
@@ -165,19 +162,19 @@ void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods
if (key == GLFW_KEY_F11 || key == GLFW_KEY_ESCAPE) { if (key == GLFW_KEY_F11 || key == GLFW_KEY_ESCAPE) {
/* /*
// Toggle fullscreen // Toggle fullscreen
GLFWmonitor *monitor = glfwGetWindowMonitor(window);
GLFWmonitor *monitor = glfwGetWindowMonitor(gWindow);
if (monitor) { if (monitor) {
// Window mode // Window mode
glfwSetWindowMonitor(window, NULL, lastWindowX, lastWindowY, lastWindowWidth, lastWindowHeight, 0);
glfwSetWindowMonitor(gWindow, NULL, lastWindowX, lastWindowY, lastWindowWidth, lastWindowHeight, 0);
} }
else { else {
// Fullscreen // Fullscreen
glfwGetWindowPos(window, &lastWindowX, &lastWindowY);
glfwGetWindowSize(window, &lastWindowWidth, &lastWindowHeight);
glfwGetWindowPos(gWindow, &lastWindowX, &lastWindowY);
glfwGetWindowSize(gWindow, &lastWindowWidth, &lastWindowHeight);
monitor = glfwGetPrimaryMonitor(); monitor = glfwGetPrimaryMonitor();
assert(monitor); assert(monitor);
const GLFWvidmode *mode = glfwGetVideoMode(monitor); const GLFWvidmode *mode = glfwGetVideoMode(monitor);
glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
glfwSetWindowMonitor(gWindow, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
} }
*/ */
} }
@@ -195,12 +192,12 @@ void errorCallback(int error, const char *description) {


void renderGui() { void renderGui() {
int width, height; int width, height;
glfwGetFramebufferSize(window, &width, &height);
glfwGetFramebufferSize(gWindow, &width, &height);
int windowWidth, windowHeight; int windowWidth, windowHeight;
glfwGetWindowSize(window, &windowWidth, &windowHeight);
glfwGetWindowSize(gWindow, &windowWidth, &windowHeight);
gPixelRatio = (float)width / windowWidth; gPixelRatio = (float)width / windowWidth;


bool visible = glfwGetWindowAttrib(window, GLFW_VISIBLE) && !glfwGetWindowAttrib(window, GLFW_ICONIFIED);
bool visible = glfwGetWindowAttrib(gWindow, GLFW_VISIBLE) && !glfwGetWindowAttrib(gWindow, GLFW_ICONIFIED);
if (visible) { if (visible) {
// Update and render // Update and render
glViewport(0, 0, width, height); glViewport(0, 0, width, height);
@@ -218,7 +215,7 @@ void renderGui() {
nvgEndFrame(gVg); nvgEndFrame(gVg);
} }


glfwSwapBuffers(window);
glfwSwapBuffers(gWindow);
} }


void guiInit() { void guiInit() {
@@ -237,19 +234,19 @@ void guiInit() {
// glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_MAXIMIZED, GLFW_TRUE); glfwWindowHint(GLFW_MAXIMIZED, GLFW_TRUE);
std::string title = gApplicationName + " " + gApplicationVersion; std::string title = gApplicationName + " " + gApplicationVersion;
window = glfwCreateWindow(1000, 750, title.c_str(), NULL, NULL);
assert(window);
glfwMakeContextCurrent(window);
gWindow = glfwCreateWindow(1000, 750, title.c_str(), NULL, NULL);
assert(gWindow);
glfwMakeContextCurrent(gWindow);


glfwSwapInterval(1); glfwSwapInterval(1);


glfwSetWindowSizeCallback(window, windowSizeCallback);
glfwSetMouseButtonCallback(window, mouseButtonCallback);
// glfwSetCursorPosCallback(window, cursorPosCallback);
glfwSetCursorEnterCallback(window, cursorEnterCallback);
glfwSetScrollCallback(window, scrollCallback);
glfwSetCharCallback(window, charCallback);
glfwSetKeyCallback(window, keyCallback);
glfwSetWindowSizeCallback(gWindow, windowSizeCallback);
glfwSetMouseButtonCallback(gWindow, mouseButtonCallback);
// glfwSetCursorPosCallback(gWindow, cursorPosCallback);
glfwSetCursorEnterCallback(gWindow, cursorEnterCallback);
glfwSetScrollCallback(gWindow, scrollCallback);
glfwSetCharCallback(gWindow, charCallback);
glfwSetKeyCallback(gWindow, keyCallback);


// Set up GLEW // Set up GLEW
glewExperimental = GL_TRUE; glewExperimental = GL_TRUE;
@@ -262,7 +259,7 @@ void guiInit() {
// GLEW generates GL error because it calls glGetString(GL_EXTENSIONS), we'll consume it here. // GLEW generates GL error because it calls glGetString(GL_EXTENSIONS), we'll consume it here.
glGetError(); glGetError();


glfwSetWindowSizeLimits(window, 640, 480, GLFW_DONT_CARE, GLFW_DONT_CARE);
glfwSetWindowSizeLimits(gWindow, 640, 480, GLFW_DONT_CARE, GLFW_DONT_CARE);


// Set up NanoVG // Set up NanoVG
gVg = nvgCreateGL2(NVG_ANTIALIAS); gVg = nvgCreateGL2(NVG_ANTIALIAS);
@@ -279,26 +276,26 @@ void guiDestroy() {
gGuiFont.reset(); gGuiFont.reset();
nvgDeleteGL2(gVg); nvgDeleteGL2(gVg);
// nvgDeleteGL3(gVg); // nvgDeleteGL3(gVg);
glfwDestroyWindow(window);
glfwDestroyWindow(gWindow);
glfwTerminate(); glfwTerminate();
} }


void guiRun() { void guiRun() {
assert(window);
assert(gWindow);
{ {
int width, height; int width, height;
glfwGetWindowSize(window, &width, &height);
windowSizeCallback(window, width, height);
glfwGetWindowSize(gWindow, &width, &height);
windowSizeCallback(gWindow, width, height);
} }
gGuiFrame = 0; gGuiFrame = 0;
double lastTime = 0.0; double lastTime = 0.0;
while(!glfwWindowShouldClose(window)) {
while(!glfwWindowShouldClose(gWindow)) {
gGuiFrame++; gGuiFrame++;
glfwPollEvents(); glfwPollEvents();
{ {
double xpos, ypos; double xpos, ypos;
glfwGetCursorPos(window, &xpos, &ypos);
cursorPosCallback(window, xpos, ypos);
glfwGetCursorPos(gWindow, &xpos, &ypos);
cursorPosCallback(gWindow, xpos, ypos);
} }
gScene->step(); gScene->step();


@@ -311,20 +308,16 @@ void guiRun() {
} }
} }


bool guiIsKeyPressed(int key) {
return glfwGetKey(window, key) == GLFW_PRESS;
}

void guiCursorLock() { void guiCursorLock() {
#ifdef ARCH_MAC #ifdef ARCH_MAC
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
glfwSetInputMode(gWindow, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
#else #else
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
glfwSetInputMode(gWindow, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
#endif #endif
} }


void guiCursorUnlock() { void guiCursorUnlock() {
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
glfwSetInputMode(gWindow, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
} }






+ 25
- 5
src/widgets/TextField.cpp View File

@@ -30,12 +30,9 @@ Widget *TextField::onMouseDown(Vec pos, int button) {




void TextField::onText(int codepoint) { void TextField::onText(int codepoint) {
if (begin < end)
text.erase(begin, end - begin);
char c = codepoint; char c = codepoint;
text.insert(begin, &c, 1);
begin++;
end = begin;
std::string newText(1, c);
insertText(newText);
} }


void TextField::onKey(int key) { void TextField::onKey(int key) {
@@ -83,6 +80,21 @@ void TextField::onKey(int key) {
case GLFW_KEY_END: case GLFW_KEY_END:
end = begin = text.size(); end = begin = text.size();
break; break;
case GLFW_KEY_V:
if (guiIsModPressed()) {
const char *newText = glfwGetClipboardString(gWindow);
if (newText)
insertText(newText);
}
break;
case GLFW_KEY_C:
if (guiIsModPressed()) {
if (begin < end) {
std::string selectedText = text.substr(begin, end - begin);
glfwSetClipboardString(gWindow, selectedText.c_str());
}
}
break;
} }


begin = mini(maxi(begin, 0), text.size()); begin = mini(maxi(begin, 0), text.size());
@@ -94,5 +106,13 @@ void TextField::onSelect() {
end = text.size(); end = text.size();
} }


void TextField::insertText(std::string newText) {
if (begin < end)
text.erase(begin, end - begin);
text.insert(begin, newText);
begin += newText.size();
end = begin;
}



} // namespace rack } // namespace rack

Loading…
Cancel
Save