Browse Source

Refactor TextField key commands.

tags/v2.0.0
Andrew Belt 4 years ago
parent
commit
e6b25a6394
1 changed files with 70 additions and 42 deletions
  1. +70
    -42
      src/ui/TextField.cpp

+ 70
- 42
src/ui/TextField.cpp View File

@@ -56,93 +56,107 @@ void TextField::onSelectText(const event::SelectText& e) {
}

void TextField::onSelectKey(const event::SelectKey& e) {
auto cursorToPrevWord = [&]() {
size_t pos = text.rfind(' ', std::max(cursor - 2, 0));
if (pos == std::string::npos)
cursor = 0;
else
cursor = pos;
};
auto cursorToNextWord = [&]() {
size_t pos = text.find(' ', std::min(cursor + 1, (int) text.size()));
if (pos == std::string::npos)
pos = text.size();
cursor = pos;
};

if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) {
// Backspace
if (e.key == GLFW_KEY_BACKSPACE && (e.mods & RACK_MOD_MASK) == 0) {
if (cursor == selection) {
cursor--;
if (cursor >= 0) {
text.erase(cursor, 1);
event::Change eChange;
onChange(eChange);
}
selection = cursor;
cursor = std::max(cursor - 1, 0);
}
else {
int begin = std::min(cursor, selection);
text.erase(begin, std::abs(selection - cursor));
event::Change eChange;
onChange(eChange);
cursor = selection = begin;
insertText("");
e.consume(this);
}
// Ctrl+Backspace
if (e.key == GLFW_KEY_BACKSPACE && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
if (cursor == selection) {
cursorToPrevWord();
}
insertText("");
e.consume(this);
}
// Delete
if (e.key == GLFW_KEY_DELETE && (e.mods & RACK_MOD_MASK) == 0) {
if (cursor == selection) {
text.erase(cursor, 1);
event::Change eChange;
onChange(eChange);
cursor = std::min(cursor + 1, (int) text.size());
}
else {
int begin = std::min(cursor, selection);
text.erase(begin, std::abs(selection - cursor));
event::Change eChange;
onChange(eChange);
cursor = selection = begin;
insertText("");
e.consume(this);
}
// Ctrl+Delete
if (e.key == GLFW_KEY_DELETE && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
if (cursor == selection) {
cursorToNextWord();
}
insertText("");
e.consume(this);
}
// Left
if (e.key == GLFW_KEY_LEFT) {
if (e.mods & RACK_MOD_CTRL) {
while (--cursor > 0) {
if (text[cursor - 1] == ' ')
break;
}
if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
cursorToPrevWord();
}
else {
cursor--;
cursor = std::max(cursor - 1, 0);
}
if (!(e.mods & GLFW_MOD_SHIFT)) {
selection = cursor;
}
e.consume(this);
}
// Right
if (e.key == GLFW_KEY_RIGHT) {
if (e.mods & RACK_MOD_CTRL) {
while (++cursor < (int) text.size()) {
if (text[cursor] == ' ')
break;
}
if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
cursorToNextWord();
}
else {
cursor++;
cursor = std::min(cursor + 1, (int) text.size());
}
if (!(e.mods & GLFW_MOD_SHIFT)) {
selection = cursor;
}
e.consume(this);
}
// Home
if (e.key == GLFW_KEY_HOME && (e.mods & RACK_MOD_MASK) == 0) {
selection = cursor = 0;
e.consume(this);
}
// Shift+Home
if (e.key == GLFW_KEY_HOME && (e.mods & RACK_MOD_MASK) == GLFW_MOD_SHIFT) {
cursor = 0;
e.consume(this);
}
// End
if (e.key == GLFW_KEY_END && (e.mods & RACK_MOD_MASK) == 0) {
selection = cursor = text.size();
e.consume(this);
}
// Shift+End
if (e.key == GLFW_KEY_END && (e.mods & RACK_MOD_MASK) == GLFW_MOD_SHIFT) {
cursor = text.size();
e.consume(this);
}
// Ctrl+V
if (e.keyName == "v" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
const char* newText = glfwGetClipboardString(APP->window->win);
if (newText)
insertText(newText);
e.consume(this);
}
// Ctrl+C
if (e.keyName == "x" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
if (cursor != selection) {
int begin = std::min(cursor, selection);
@@ -152,6 +166,7 @@ void TextField::onSelectKey(const event::SelectKey& e) {
}
e.consume(this);
}
// Ctrl+C
if (e.keyName == "c" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
if (cursor != selection) {
int begin = std::min(cursor, selection);
@@ -160,10 +175,12 @@ void TextField::onSelectKey(const event::SelectKey& e) {
}
e.consume(this);
}
// Ctrl+A
if (e.keyName == "a" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
selectAll();
e.consume(this);
}
// Enter
if ((e.key == GLFW_KEY_ENTER || e.key == GLFW_KEY_KP_ENTER) && (e.mods & RACK_MOD_MASK) == 0) {
if (multiline) {
insertText("\n");
@@ -178,30 +195,41 @@ void TextField::onSelectKey(const event::SelectKey& e) {
if (e.keyName != "") {
e.consume(this);
}
// Esc
if (e.key == GLFW_KEY_ESCAPE && (e.mods & RACK_MOD_MASK) == 0) {
APP->event->setSelected(NULL);
e.consume(this);
}

cursor = math::clamp(cursor, 0, (int) text.size());
selection = math::clamp(selection, 0, (int) text.size());
assert(0 <= cursor);
assert(cursor <= (int) text.size());
assert(0 <= selection);
assert(selection <= (int) text.size());
}

// Consume ALL keys with ALL actions. Is this bad? I don't know, need more testing.
// Consume ALL keys with ALL actions
e.consume(this);
}

void TextField::insertText(std::string text) {
bool changed = false;
if (cursor != selection) {
// Delete selected text
int begin = std::min(cursor, selection);
this->text.erase(begin, std::abs(selection - cursor));
cursor = selection = begin;
changed = true;
}
if (!text.empty()) {
this->text.insert(cursor, text);
cursor += text.size();
selection = cursor;
changed = true;
}
if (changed) {
event::Change eChange;
onChange(eChange);
}
this->text.insert(cursor, text);
cursor += text.size();
selection = cursor;
event::Change eChange;
onChange(eChange);
}

void TextField::setText(std::string text) {


Loading…
Cancel
Save